Subject: | Terminating during unpack results in corrupted cache, failure on next start |
If a compiled script is killed while writing out its archive, a partially-written cache file may result
(often a short extraction of libperl.so, as that tends to be the largest file in the archive). The
present code in myldr/boot.c:extract_embedded_file() is willing to write a missing file, but not
overwrite a partially-written file (one where the size in the archive differs from the size on the
filesystem), resulting in an abort with a fatal "file exists" error.
The attached patch permits the loader to overwrite a corrupt file. I added a warning to stderr to
report this condition, but that may or may not be appropriate. It was a useful diagnostic aid for
my purposes.
Subject: | boot.c.diff |
--- boot.c.orig 2013-01-22 14:05:26.000000000 -0800
+++ boot.c.patched 2013-01-23 10:48:44.000000000 -0800
@@ -37,11 +37,21 @@
fd = open(*ext_path, O_CREAT | O_EXCL | O_WRONLY | OPEN_O_BINARY, 0755);
if ( fd == -1 ) {
struct stat statbuf;
- if ( errno == EEXIST
- && par_lstat(*ext_path, &statbuf) == 0
- && statbuf.st_size == emb_file->size )
- return 1; /* file already exists and has the expected size */
- return 0;
+ if ( errno == EEXIST ) {
+ if ( par_lstat(*ext_path, &statbuf) == 0
+ && statbuf.st_size == emb_file->size ) {
+ return 1; /* file already exists and has the expected size */
+ } else {
+ /* Try to reopen for rewrite */
+ fprintf(stderr, "extract_embedded_file(%s): rewriting due to size mismatch\n", *ext_path);
+ fd = open(*ext_path, O_CREAT | O_WRONLY | OPEN_O_BINARY, 0755);
+ if ( fd == -1 ) {
+ return 0;
+ }
+ }
+ } else {
+ return 0;
+ }
}
chunk = emb_file->chunks;