Save images to a temporary file first, then call MOVE_FILE to avoid writing incomplete and truncated images.

db4
Doug Coleman 2010-01-20 22:40:25 -06:00
parent 07fcb43a06
commit bb2f455747
8 changed files with 43 additions and 20 deletions

View File

@ -516,9 +516,9 @@ M: bad-executable summary
\ compact-gc { } { } define-primitive \ compact-gc { } { } define-primitive
\ (save-image) { byte-array } { } define-primitive \ (save-image) { byte-array byte-array } { } define-primitive
\ (save-image-and-exit) { byte-array } { } define-primitive \ (save-image-and-exit) { byte-array byte-array } { } define-primitive
\ data-room { } { byte-array } define-primitive \ data-room { } { byte-array } define-primitive
\ data-room make-flushable \ data-room make-flushable

View File

@ -511,8 +511,8 @@ tuple
{ "gc" "memory" "primitive_full_gc" (( -- )) } { "gc" "memory" "primitive_full_gc" (( -- )) }
{ "minor-gc" "memory" "primitive_minor_gc" (( -- )) } { "minor-gc" "memory" "primitive_minor_gc" (( -- )) }
{ "size" "memory" "primitive_size" (( obj -- n )) } { "size" "memory" "primitive_size" (( obj -- n )) }
{ "(save-image)" "memory.private" "primitive_save_image" (( path -- )) } { "(save-image)" "memory.private" "primitive_save_image" (( path1 path2 -- )) }
{ "(save-image-and-exit)" "memory.private" "primitive_save_image_and_exit" (( path -- )) } { "(save-image-and-exit)" "memory.private" "primitive_save_image_and_exit" (( path1 path2 -- )) }
{ "jit-compile" "quotations" "primitive_jit_compile" (( quot -- )) } { "jit-compile" "quotations" "primitive_jit_compile" (( quot -- )) }
{ "quot-compiled?" "quotations" "primitive_quot_compiled_p" (( quot -- ? )) } { "quot-compiled?" "quotations" "primitive_quot_compiled_p" (( quot -- ? )) }
{ "quotation-code" "quotations" "primitive_quotation_code" (( quot -- start end )) } { "quotation-code" "quotations" "primitive_quotation_code" (( quot -- start end )) }

View File

@ -1,16 +1,20 @@
! Copyright (C) 2005, 2009 Slava Pestov. ! Copyright (C) 2005, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel continuations sequences system USING: alien.strings io.backend io.pathnames kernel
io.backend alien.strings memory.private ; memory.private sequences system ;
IN: memory IN: memory
: instances ( quot -- seq ) : instances ( quot -- seq )
[ all-instances ] dip filter ; inline [ all-instances ] dip filter ; inline
: saving-path ( path -- saving-path path )
[ ".saving" append-path ] keep
[ native-string>alien ] bi@ ;
: save-image ( path -- ) : save-image ( path -- )
normalize-path native-string>alien (save-image) ; normalize-path saving-path (save-image) ;
: save-image-and-exit ( path -- ) : save-image-and-exit ( path -- )
normalize-path native-string>alien (save-image-and-exit) ; normalize-path saving-path (save-image-and-exit) ;
: save ( -- ) image save-image ; : save ( -- ) image save-image ;

View File

@ -442,7 +442,7 @@ void factor_vm::factorbug()
else if(strcmp(cmd,"x") == 0) else if(strcmp(cmd,"x") == 0)
exit(1); exit(1);
else if(strcmp(cmd,"im") == 0) else if(strcmp(cmd,"im") == 0)
save_image(STRING_LITERAL("fep.image")); save_image(STRING_LITERAL("fep.image.saving"),STRING_LITERAL("fep.image"));
else if(strcmp(cmd,"data") == 0) else if(strcmp(cmd,"data") == 0)
dump_objects(TYPE_COUNT); dump_objects(TYPE_COUNT);
else if(strcmp(cmd,"refs") == 0) else if(strcmp(cmd,"refs") == 0)

View File

@ -268,12 +268,12 @@ void factor_vm::load_image(vm_parameters *p)
} }
/* Save the current image to disk */ /* Save the current image to disk */
bool factor_vm::save_image(const vm_char *filename) bool factor_vm::save_image(const vm_char *saving_filename, const vm_char *filename)
{ {
FILE* file; FILE* file;
image_header h; image_header h;
file = OPEN_WRITE(filename); file = OPEN_WRITE(saving_filename);
if(file == NULL) if(file == NULL)
{ {
std::cout << "Cannot open image file: " << filename << std::endl; std::cout << "Cannot open image file: " << filename << std::endl;
@ -303,6 +303,7 @@ bool factor_vm::save_image(const vm_char *filename)
if(safe_fwrite(code->allocator->first_block(),h.code_size,1,file) != 1) ok = false; if(safe_fwrite(code->allocator->first_block(),h.code_size,1,file) != 1) ok = false;
if(safe_fclose(file)) ok = false; if(safe_fclose(file)) ok = false;
MOVE_FILE(saving_filename,filename);
if(!ok) if(!ok)
std::cout << "save-image failed: " << strerror(errno) << std::endl; std::cout << "save-image failed: " << strerror(errno) << std::endl;
@ -314,9 +315,11 @@ void factor_vm::primitive_save_image()
/* do a full GC to push everything into tenured space */ /* do a full GC to push everything into tenured space */
primitive_compact_gc(); primitive_compact_gc();
data_root<byte_array> path(ctx->pop(),this); data_root<byte_array> path1(ctx->pop(),this);
path.untag_check(this); path1.untag_check(this);
save_image((vm_char *)(path.untagged() + 1)); data_root<byte_array> path2(ctx->pop(),this);
path2.untag_check(this);
save_image((vm_char *)(path1.untagged() + 1 ),(vm_char *)(path2.untagged() + 1));
} }
void factor_vm::primitive_save_image_and_exit() void factor_vm::primitive_save_image_and_exit()
@ -324,8 +327,10 @@ void factor_vm::primitive_save_image_and_exit()
/* We unbox this before doing anything else. This is the only point /* We unbox this before doing anything else. This is the only point
where we might throw an error, so we have to throw an error here since where we might throw an error, so we have to throw an error here since
later steps destroy the current image. */ later steps destroy the current image. */
data_root<byte_array> path(ctx->pop(),this); data_root<byte_array> path1(ctx->pop(),this);
path.untag_check(this); path1.untag_check(this);
data_root<byte_array> path2(ctx->pop(),this);
path2.untag_check(this);
/* strip out special_objects data which is set on startup anyway */ /* strip out special_objects data which is set on startup anyway */
for(cell i = 0; i < special_object_count; i++) for(cell i = 0; i < special_object_count; i++)
@ -336,7 +341,7 @@ void factor_vm::primitive_save_image_and_exit()
false /* discard objects only reachable from stacks */); false /* discard objects only reachable from stacks */);
/* Save the image */ /* Save the image */
if(save_image((vm_char *)(path.untagged() + 1))) if(save_image((vm_char *)(path1.untagged() + 1), (vm_char *)(path2.untagged() + 1)))
exit(0); exit(0);
else else
exit(1); exit(1);

View File

@ -31,6 +31,15 @@ typedef char symbol_char;
#define OPEN_READ(path) fopen(path,"rb") #define OPEN_READ(path) fopen(path,"rb")
#define OPEN_WRITE(path) fopen(path,"wb") #define OPEN_WRITE(path) fopen(path,"wb")
#define MOVE_FILE(path1,path2) \
do {\
int ret = 0;\
do {\
ret = rename((path1),(path2));\
} while(ret < 0 && errno == EINTR);\
if(ret < 0)\
general_error(ERROR_IO,tag_fixnum(errno),false_object,NULL);\
}while(0)
#define print_native_string(string) print_string(string) #define print_native_string(string) print_string(string)

View File

@ -37,8 +37,13 @@ typedef wchar_t vm_char;
#define CELL_HEX_FORMAT "%lx" #define CELL_HEX_FORMAT "%lx"
#endif #endif
#define OPEN_READ(path) _wfopen(path,L"rb") #define OPEN_READ(path) _wfopen((path),L"rb")
#define OPEN_WRITE(path) _wfopen(path,L"wb") #define OPEN_WRITE(path) _wfopen((path),L"wb")
#define MOVE_FILE(path1,path2) \
do {\
if(MoveFile((path1),(path2)) == 0)\
general_error(ERROR_IO,tag_fixnum(GetLastError()),false_object,NULL);\
} while(0)
/* Difference between Jan 1 00:00:00 1601 and Jan 1 00:00:00 1970 */ /* Difference between Jan 1 00:00:00 1601 and Jan 1 00:00:00 1970 */
#define EPOCH_OFFSET 0x019db1ded53e8000LL #define EPOCH_OFFSET 0x019db1ded53e8000LL

View File

@ -549,7 +549,7 @@ struct factor_vm
void init_objects(image_header *h); void init_objects(image_header *h);
void load_data_heap(FILE *file, image_header *h, vm_parameters *p); void load_data_heap(FILE *file, image_header *h, vm_parameters *p);
void load_code_heap(FILE *file, image_header *h, vm_parameters *p); void load_code_heap(FILE *file, image_header *h, vm_parameters *p);
bool save_image(const vm_char *filename); bool save_image(const vm_char *saving_filename, const vm_char *filename);
void primitive_save_image(); void primitive_save_image();
void primitive_save_image_and_exit(); void primitive_save_image_and_exit();
void fixup_data(cell data_offset, cell code_offset); void fixup_data(cell data_offset, cell code_offset);