VM: new functions raw_fclose and raw_fread

These need to be used when the image is loaded because there is no
context so you can't throw io errors yet.
db4
Björn Lindqvist 2015-05-30 02:29:57 +02:00
parent 9d289e35f4
commit f1ca83524a
3 changed files with 42 additions and 24 deletions

View File

@ -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); init_data_heap(p->young_size, p->aging_size, p->tenured_size);
fixnum bytes_read = 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) { if ((cell)bytes_read != h->data_size) {
std::cout << "truncated image: " << bytes_read << " bytes read, "; 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) { if (h->code_size != 0) {
size_t bytes_read = 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) { if (bytes_read != h->code_size) {
std::cout << "truncated image: " << bytes_read << " bytes read, "; std::cout << "truncated image: " << bytes_read << " bytes read, ";
std::cout << h->code_size << " bytes expected\n"; std::cout << h->code_size << " bytes expected\n";
@ -239,9 +239,8 @@ void factor_vm::load_image(vm_parameters* p) {
free(msg); free(msg);
exit(1); exit(1);
} }
image_header h; 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); fatal_error("Cannot read image header", 0);
if (h.magic != image_magic) if (h.magic != image_magic)
@ -253,7 +252,7 @@ void factor_vm::load_image(vm_parameters* p) {
load_data_heap(file, &h, p); load_data_heap(file, &h, p);
load_code_heap(file, &h, p); load_code_heap(file, &h, p);
safe_fclose(file); raw_fclose(file);
init_objects(&h); init_objects(&h);

View File

@ -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 with many more capabilities so these words are not usually used in
normal operation. */ 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() { void factor_vm::init_c_io() {
special_objects[OBJ_STDIN] = allot_alien(false_object, (cell)stdin); special_objects[OBJ_STDIN] = allot_alien(false_object, (cell)stdin);
special_objects[OBJ_STDOUT] = allot_alien(false_object, (cell)stdout); 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, size_t factor_vm::safe_fread(void* ptr, size_t size, size_t nitems,
FILE* stream) { FILE* stream) {
size_t items_read = 0; size_t ret = raw_fread(ptr, size, nitems, stream);
size_t ret = 0; if (!ret)
io_error_if_not_EINTR();
do { return ret;
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;
} }
void factor_vm::safe_fputc(int c, FILE* stream) { 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) { void factor_vm::safe_fclose(FILE* stream) {
if (fclose(stream) == EOF && errno != EINTR) if (raw_fclose(stream) == -1)
general_error(ERROR_IO, tag_fixnum(errno), false_object); io_error_if_not_EINTR();
} }
void factor_vm::primitive_fopen() { void factor_vm::primitive_fopen() {

View File

@ -1,5 +1,9 @@
namespace factor { 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 */ /* Platform specific primitives */
VM_C_API int err_no(); VM_C_API int err_no();