This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch master in repository x2goserver. commit aaa5b2236d03e5101618603087885a3667746b9d Author: Mihai Moldovan <ionic@ionic.de> Date: Sat Jul 21 23:58:25 2018 +0200 x2goserver-printing/bin/x2goprint: work around atomicity problems with newer FUSE versions, create .ready file as .notready, move/copy to target file system and only then rename it in a hopefully atomic fashion. --- debian/changelog | 4 ++++ x2goserver-printing/bin/x2goprint | 32 ++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/debian/changelog b/debian/changelog index b852eeb..cc5df9c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -118,6 +118,10 @@ x2goserver (4.1.0.1-0x2go1) UNRELEASED; urgency=medium nxagent. Fixes: #1266. - x2goserver/bin/x2gostartagent: fix calculation syntax errors, drop useless subshells, don't use -o operator in plain test calls. + - x2goserver-printing/bin/x2goprint: work around atomicity problems with + newer FUSE versions, create .ready file as .notready, move/copy to + target file system and only then rename it in a hopefully atomic + fashion. * debian/{control,compat}: + Bump DH compat level to 9. * debian/: diff --git a/x2goserver-printing/bin/x2goprint b/x2goserver-printing/bin/x2goprint index d436a6b..c1ea0b6 100755 --- a/x2goserver-printing/bin/x2goprint +++ b/x2goserver-printing/bin/x2goprint @@ -119,14 +119,38 @@ if ( $mounts=~m/$spooldir/) system("su", "$user", "-c", "mv $spooltmp/$pdfFile $spooldir"); syslog('debug', "x2goprint moved file $pdfFile to X2Go client's spool dir"); - open (RFILE,">$spooltmp/$pdfFile.ready"); + # Different fuse versions seem to handle cross-boundary moves differently. + # Older fuse versions seem to move files atomically (which is what we expect), i.e., + # the file turns up on the remote file system fully populated. + # Newer fuse versions first create the file and then populate it, leading to a race + # condition with X2Go Client: + # - X2Go Client sees the .ready file + # - immediately tries to read its content + # - deletes the file + # + # To further understand what is happening, consider that an mv operation is only + # (somewhat) guaranteed to be atomic for moves within a file system. In this case, + # mv uses the rename(2) system call, which, according to POSIX/SUS shall be atomic + # in certain cases (though it seems to only hold when the target file already + # exists). Then again, the C standard itself, which POSIX is also referencing, + # does not make any guarantees when it comes to atomicity, rather it says that the + # behavior is "implementation-defined" when the target file already exists. When + # crossing boundaries, all bets are off. Such an operation might be atomic, but + # might also be implemented as the equivalent of cp && rm. + # + # We'll handle this by generating a temporary file on the local server file system + # (suffixed .notready), copying that to the fuse mount and then issuing a fs-local + # mv/rename operation that we really, really, really hope will be atomic. + open (RFILE,">$spooltmp/$pdfFile.notready"); print RFILE "$pdfFile\n$title"; close (RFILE); - chown $uid, $gid, "$spooltmp/$pdfFile.ready"; - system ("su", "$user", "-c", "mv $spooltmp/$pdfFile.ready $spooldir"); - syslog('debug', "x2goprint moved file $pdfFile.ready to X2Go client's spool dir, X2Go client should start the print dialog very soon"); + chown $uid, $gid, "$spooltmp/$pdfFile.notready"; + system ("su", "$user", "-c", "mv $spooltmp/$pdfFile.notready $spooldir"); + + system ("su", "$user", "-c", "mv $spooldir/$pdfFile.notready $spooldir/$pdfFile.ready"); + syslog('debug', "x2goprint moved file $pdfFile.ready to X2Go client's spool dir, X2Go client should start the print dialog very soon"); } else { # if the client-side spool dir is not mounted via SSHFS, we will simply drop the -- Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/x2goserver.git