From: Arvin Schnell Date: Fri, 18 Jan 2019 11:07:09 +0000 (+0100) Subject: - avoid deadlock for special btrfs directory comparison (bsc#1049574) X-Git-Tag: v0.8.2~2^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F471%2Fhead;p=thirdparty%2Fsnapper.git - avoid deadlock for special btrfs directory comparison (bsc#1049574) --- diff --git a/package/snapper.changes b/package/snapper.changes index 652e62cf..a01e08ea 100644 --- a/package/snapper.changes +++ b/package/snapper.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Jan 18 10:45:54 CET 2019 - aschnell@suse.com + +- avoid deadlock for special btrfs directory comparison + (bsc#1049574) + ------------------------------------------------------------------- Wed Nov 21 18:59:09 CET 2018 - gergo@borus.hu diff --git a/snapper/Btrfs.cc b/snapper/Btrfs.cc index cacc8349..e54cacf1 100644 --- a/snapper/Btrfs.cc +++ b/snapper/Btrfs.cc @@ -1238,9 +1238,43 @@ namespace snapper }; + struct FdCloser + { + FdCloser(int fd) + : fd(fd) + { + } + + ~FdCloser() + { + if (fd > -1 ) + ::close(fd); + } + + void reset() + { + fd = -1; + } + + int close() + { + int r = ::close(fd); + fd = -1; + return r; + } + + private: + + int fd; + + }; + + bool StreamProcessor::dumper(int fd) { + FdCloser fd_closer(fd); + while (true) { boost::this_thread::interruption_point(); @@ -1256,7 +1290,7 @@ namespace snapper if (r < 0) { - y2err("btrfs_read_and_process_send_stream failed"); + y2err("btrfs_read_and_process_send_stream failed " << r); #if BOOST_VERSION < 104100 dumper_ret = false; @@ -1289,6 +1323,10 @@ namespace snapper SN_THROW(BtrfsSendReceiveException()); } + // Use RAII to help close fds. + FdCloser fd0_closer(pipefd[0]); + FdCloser fd1_closer(pipefd[1]); + struct btrfs_ioctl_send_args io_send; memset(&io_send, 0, sizeof(io_send)); io_send.send_fd = pipefd[1]; @@ -1304,18 +1342,18 @@ namespace snapper boost::thread task(boost::move(pt)); + fd0_closer.reset(); + int r2 = ioctl(dir2.fd(), BTRFS_IOC_SEND, &io_send); if (r2 < 0) { y2err("send ioctl failed errno:" << errno << " (" << stringerror(errno) << ")"); } - close(pipefd[1]); + fd1_closer.close(); uf.wait(); - close(pipefd[0]); - if (r2 < 0 || !uf.get()) { SN_THROW(BtrfsSendReceiveException()); @@ -1325,18 +1363,18 @@ namespace snapper boost::thread dumper_thread(boost::bind(&StreamProcessor::dumper, this, pipefd[0])); + fd0_closer.reset(); + int r2 = ioctl(dir2.fd(), BTRFS_IOC_SEND, &io_send); if (r2 < 0) { y2err("send ioctl failed errno:" << errno << " (" << stringerror(errno) << ")"); } - close(pipefd[1]); + fd1_closer.close(); dumper_thread.join(); - close(pipefd[0]); - if (r2 < 0 || !dumper_ret) { SN_THROW(BtrfsSendReceiveException());