diff --git a/basis/stack-checker/known-words/known-words.factor b/basis/stack-checker/known-words/known-words.factor index 9bc61c6353..6ac668b031 100644 --- a/basis/stack-checker/known-words/known-words.factor +++ b/basis/stack-checker/known-words/known-words.factor @@ -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 diff --git a/core/bootstrap/primitives.factor b/core/bootstrap/primitives.factor index dde5463c0f..2288b89cf4 100644 --- a/core/bootstrap/primitives.factor +++ b/core/bootstrap/primitives.factor @@ -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 )) } diff --git a/core/memory/memory.factor b/core/memory/memory.factor index 4ab68a1ef1..0fba4dee77 100644 --- a/core/memory/memory.factor +++ b/core/memory/memory.factor @@ -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 ; diff --git a/vm/debug.cpp b/vm/debug.cpp index 419eb690ff..e82394951a 100755 --- a/vm/debug.cpp +++ b/vm/debug.cpp @@ -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) diff --git a/vm/image.cpp b/vm/image.cpp index 54bd2f706d..bfc9f3daca 100755 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -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 path(ctx->pop(),this); - path.untag_check(this); - save_image((vm_char *)(path.untagged() + 1)); + data_root path1(ctx->pop(),this); + path1.untag_check(this); + data_root 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 path(ctx->pop(),this); - path.untag_check(this); + data_root path1(ctx->pop(),this); + path1.untag_check(this); + data_root 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); diff --git a/vm/os-unix.hpp b/vm/os-unix.hpp index 7faab4d8b8..5efa62919d 100644 --- a/vm/os-unix.hpp +++ b/vm/os-unix.hpp @@ -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) diff --git a/vm/os-windows.hpp b/vm/os-windows.hpp index 8a2dfe38f5..0569d85b61 100755 --- a/vm/os-windows.hpp +++ b/vm/os-windows.hpp @@ -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 diff --git a/vm/vm.hpp b/vm/vm.hpp index 6f826ed9e0..6fb788d531 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -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);