In case you didn’t see it: rfm has recently submitted a change which repeatedly 
compares modification date.
On 6 October 2016 at 18:11:42, Lobron, David ([email protected]) wrote:

I just realized that this is likely being caused by a change to the target file 
(made by a different process).  

Would it make sense for NSFileManager::copyPath to periodically recompute the 
file size, and to throw an exception if it changes? The current code has a race 
condition between the initial file size calculation and the read/write loop. If 
the file gets smaller, it will hit EOF before the loop hits its exit condition, 
and the loop will never finish.  

--David  

> On Oct 6, 2016, at 12:02 PM, Lobron, David <[email protected]> wrote:  
>  
> Hi All,  
>  
> I have an application that calls NSFileManager's copyPath:toPath:handler: 
> method on a 40MB file. I'm finding that occasionally, the copy takes an 
> extremely long time, up to a few days.  
>  
> I attached the process and found that it's bouncing between read() and 
> write() system calls in NSFileManager.m. Stack traces show either this:  
>  
> #0 0x00007efe820f389d in read () from /lib/x86_64-linux-gnu/libc.so.6  
> #1 0x00007efe83014d07 in read (__nbytes=8096, __buf=0x7ffc7a12cb00, __fd=14) 
> at /usr/include/x86_64-linux-gnu/bits/unistd.h:44  
> #2 -[NSFileManager(PrivateMethods) _copyFile:toFile:handler:] 
> (self=0x1fb45c0, _cmd=<optimized out>, source=0x2a07810, 
> destination=0x220bd730, handler=0x0)  
> at NSFileManager.m:2748  
> #3 0x00007efe830122eb in -[NSFileManager copyPath:toPath:handler:] 
> (self=0x1fb45c0, _cmd=<optimized out>, source=0x2a07810, 
> destination=0x220bd730, handler=0x0)  
> at NSFileManager.m:1109  
>  
> or this:  
>  
> #0 0x00007efe820f38fd in write () from /lib/x86_64-linux-gnu/libc.so.6  
> #1 0x00007efe83014ce1 in -[NSFileManager(PrivateMethods) 
> _copyFile:toFile:handler:] (self=0x1fb45c0, _cmd=<optimized out>, 
> source=0x2a07810, destination=0x220bd730,  
> handler=0x0) at NSFileManager.m:2761  
> #2 0x00007efe830122eb in -[NSFileManager copyPath:toPath:handler:] 
> (self=0x1fb45c0, _cmd=<optimized out>, source=0x2a07810, 
> destination=0x220bd730, handler=0x0)  
> at NSFileManager.m:1109  
>  
> I checked the process with strace, and confirmed that it's bouncing between 
> read and write, both of which are returning 0:  
>  
> read(14, "", 8096) = 0  
> write(15, "", 0) = 0  
> read(14, "", 8096) = 0  
> write(15, "", 0) = 0  
> read(14, "", 8096) = 0  
> write(15, "", 0) = 0  
> ...etc.  
>  
> The code in question is:  
>  
> /* Read bufsize bytes from source file and write them into the destination  
> file. In case of errors call the handler and abort the operation. */  
> for (i = 0; i < fileSize; i += rbytes)  
> {  
> rbytes = read (sourceFd, buffer, bufsize);  
> if (rbytes < 0)  
> {  
> close (sourceFd);  
> close (destFd);  
>  
> return [self _proceedAccordingToHandler: handler  
> forError: @"cannot read from file"  
> inPath: source  
> fromPath: source  
> toPath: destination];  
> }  
>  
> wbytes = write (destFd, buffer, rbytes);  
> if (wbytes != rbytes)  
> {  
> close (sourceFd);  
> close (destFd);  
>  
> return [self _proceedAccordingToHandler: handler  
> forError: @"cannot write to file"  
> inPath: destination  
> fromPath: source  
> toPath: destination];  
> }  
> }  
>  
> I printed out the values of i, fileSize, bufSize and rbytes:  
>  
> (gdb) print i  
> $1 = 44102943  
> (gdb) print fileSize  
> $2 = 44113575  
> (gdb) print bufsize  
> $6 = 8096  
>  
> Most interesting was the value of rbytes:  
>  
> (gdb) print rbytes  
> $4 = 0  
>  
> Later:  
>  
> (gdb) print rbytes  
> $5 = <optimized out>  
>  
> Since read is returning 0, the loop counter is not incremented. The read(2) 
> manpage says: "On success, the number of bytes read is returned (zero 
> indicates end of file), and the file position is advanced by this number. It 
> is not an error if this number is smaller than the number of bytes requested; 
> this may happen for example because fewer bytes are actually available right 
> now (maybe because we were close to end-of-file, or because we are reading 
> from a pipe, or from a terminal), or because read() was interrupted by a 
> signal."  
>  
> It seems like read is hitting EOF before we've read fileSize bytes. Or maybe 
> one of the other conditions that causes read to return less than the number 
> of bytes read is being hit. Has anyone seen this before?  
>  
> Thanks,  
>  
> David  
>  
>  
>  


_______________________________________________  
Discuss-gnustep mailing list  
[email protected]  
https://lists.gnu.org/mailman/listinfo/discuss-gnustep  
_______________________________________________
Discuss-gnustep mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/discuss-gnustep

Reply via email to