|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2002-06-17 20:14 UTC] sniper@php.net
[2002-07-23 01:00 UTC] php-bugs at lists dot php dot net
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 22:00:02 2025 UTC |
The copy() function (actually php_copy_file() at ext/standard/file.c:1934) uses mmap() when available. The mmap() function has the documented "feature" (bug!) that if the file that is mapped is truncated (e.g. by another process) after mmap() is called, a SIGBUS (bus error) signal is generated during the write() to the destination file using the mmap'ed pointer as the source of the write. This, of course, crashes php. I can not find a workaround for this. I have not been able to find any combination of flags to pass to mmap such that mmap() will fail gracefully rather than write() failing non-gracefully. Don't use mmep()? That would be a shame, but seems to be the solution. Simple example. Note that /computers/win95 is an smbmount'ed file system. The file being accessed here, a Window's swap file, is of course changing all the time. <?php copy("/computers/win95/C/WINDOWS/WIN386.SWP", "/tmp/zzz"); ?> Here's a simple C program which replicates what's going on in php_copy_file() #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> int main(int argc, char * argv[]) { int fdSrc; int fdDest; int len; char buf[8192]; void * srcfile; struct stat sbuf; if ((fdSrc = open("/computers/win95/C/WINDOWS/WIN386.SWP", 0)) < 0) { perror("open"); exit(1); } if ((fdDest = creat("/tmp/zzz", 0777)) < 0) { perror("creat"); exit(1); } if (fstat(fdSrc, &sbuf)) { perror("fstat"); exit(1); } srcfile = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, fdSrc, 0); printf("srcfile=%p\n", srcfile); if (srcfile != (void *) MAP_FAILED) { if ((len = write(fdDest, srcfile, sbuf.st_size)) != sbuf.st_size) { printf("write returned %d; expected %d\n", len, sbuf.st_size); } munmap(srcfile, sbuf.st_size); } printf("Success\n"); close(fdSrc); close(fdDest); exit(0); }