diff --git a/vm/image.cpp b/vm/image.cpp index b737455d62..45a84b1112 100644 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -18,7 +18,7 @@ void factor_vm::load_data_heap(FILE* file, image_header* h, vm_parameters* p) { init_data_heap(p->young_size, p->aging_size, p->tenured_size); fixnum bytes_read = - safe_fread((void*)data->tenured->start, 1, h->data_size, file); + raw_fread((void*)data->tenured->start, 1, h->data_size, file); if ((cell)bytes_read != h->data_size) { std::cout << "truncated image: " << bytes_read << " bytes read, "; @@ -37,7 +37,7 @@ void factor_vm::load_code_heap(FILE* file, image_header* h, vm_parameters* p) { if (h->code_size != 0) { size_t bytes_read = - safe_fread((void*)code->allocator->start, 1, h->code_size, file); + raw_fread((void*)code->allocator->start, 1, h->code_size, file); if (bytes_read != h->code_size) { std::cout << "truncated image: " << bytes_read << " bytes read, "; std::cout << h->code_size << " bytes expected\n"; @@ -239,9 +239,8 @@ void factor_vm::load_image(vm_parameters* p) { free(msg); exit(1); } - image_header h; - if (safe_fread(&h, sizeof(image_header), 1, file) != 1) + if (raw_fread(&h, sizeof(image_header), 1, file) != 1) fatal_error("Cannot read image header", 0); if (h.magic != image_magic) @@ -253,7 +252,7 @@ void factor_vm::load_image(vm_parameters* p) { load_data_heap(file, &h, p); load_code_heap(file, &h, p); - safe_fclose(file); + raw_fclose(file); init_objects(&h); diff --git a/vm/io.cpp b/vm/io.cpp index 140d6bcfa3..bdb50ac3fb 100644 --- a/vm/io.cpp +++ b/vm/io.cpp @@ -13,6 +13,34 @@ The Factor library provides platform-specific code for Unix and Windows with many more capabilities so these words are not usually used in normal operation. */ +size_t raw_fread(void* ptr, size_t size, size_t nitems, FILE* stream) { + size_t items_read = 0; + size_t ret = 0; + + do { + ret = fread((void*)((int*)ptr + items_read * size), size, + nitems - items_read, stream); + if (ret == 0) { + if (feof(stream)) + break; + else if (errno != EINTR) { + return 0; + } + } + items_read += ret; + } while (items_read != nitems); + + return items_read; +} + +// Call fclose() once only. Issues #1335, #908. +int raw_fclose(FILE* stream) { + if (fclose(stream) == EOF && errno != EINTR) + return -1; + return 0; +} + + void factor_vm::init_c_io() { special_objects[OBJ_STDIN] = allot_alien(false_object, (cell)stdin); special_objects[OBJ_STDOUT] = allot_alien(false_object, (cell)stdout); @@ -56,22 +84,10 @@ int factor_vm::safe_fgetc(FILE* stream) { size_t factor_vm::safe_fread(void* ptr, size_t size, size_t nitems, FILE* stream) { - size_t items_read = 0; - size_t ret = 0; - - do { - ret = fread((void*)((int*)ptr + items_read * size), size, - nitems - items_read, stream); - if (ret == 0) { - if (feof(stream)) - break; - else - io_error_if_not_EINTR(); - } - items_read += ret; - } while (items_read != nitems); - - return items_read; + size_t ret = raw_fread(ptr, size, nitems, stream); + if (!ret) + io_error_if_not_EINTR(); + return ret; } void factor_vm::safe_fputc(int c, FILE* stream) { @@ -142,10 +158,9 @@ void factor_vm::safe_fflush(FILE* stream) { } } -// Call fclose() once only. Issues #1335, #908. void factor_vm::safe_fclose(FILE* stream) { - if (fclose(stream) == EOF && errno != EINTR) - general_error(ERROR_IO, tag_fixnum(errno), false_object); + if (raw_fclose(stream) == -1) + io_error_if_not_EINTR(); } void factor_vm::primitive_fopen() { diff --git a/vm/io.hpp b/vm/io.hpp index 96348f47ef..59b847159d 100644 --- a/vm/io.hpp +++ b/vm/io.hpp @@ -1,5 +1,9 @@ namespace factor { +/* Safe IO functions that does not throw Factor errors. */ +int raw_fclose(FILE* stream); +size_t raw_fread(void* ptr, size_t size, size_t nitems, FILE* stream); + /* Platform specific primitives */ VM_C_API int err_no();