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
\ (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 make-flushable

View File

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

View File

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

View File

@ -442,7 +442,7 @@ void factor_vm::factorbug()
else if(strcmp(cmd,"x") == 0)
exit(1);
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)
dump_objects(TYPE_COUNT);
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 */
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;
image_header h;
file = OPEN_WRITE(filename);
file = OPEN_WRITE(saving_filename);
if(file == NULL)
{
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_fclose(file)) ok = false;
MOVE_FILE(saving_filename,filename);
if(!ok)
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 */
primitive_compact_gc();
data_root<byte_array> path(ctx->pop(),this);
path.untag_check(this);
save_image((vm_char *)(path.untagged() + 1));
data_root<byte_array> path1(ctx->pop(),this);
path1.untag_check(this);
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()
@ -324,8 +327,10 @@ void factor_vm::primitive_save_image_and_exit()
/* 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
later steps destroy the current image. */
data_root<byte_array> path(ctx->pop(),this);
path.untag_check(this);
data_root<byte_array> path1(ctx->pop(),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 */
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 */);
/* 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);
else
exit(1);

View File

@ -31,6 +31,15 @@ typedef char symbol_char;
#define OPEN_READ(path) fopen(path,"rb")
#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)

View File

@ -37,8 +37,13 @@ typedef wchar_t vm_char;
#define CELL_HEX_FORMAT "%lx"
#endif
#define OPEN_READ(path) _wfopen(path,L"rb")
#define OPEN_WRITE(path) _wfopen(path,L"wb")
#define OPEN_READ(path) _wfopen((path),L"rb")
#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 */
#define EPOCH_OFFSET 0x019db1ded53e8000LL

View File

@ -549,7 +549,7 @@ struct factor_vm
void init_objects(image_header *h);
void load_data_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_and_exit();
void fixup_data(cell data_offset, cell code_offset);