]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- avoid deadlock for special btrfs directory comparison (bsc#1049574) 471/head
authorArvin Schnell <aschnell@suse.de>
Fri, 18 Jan 2019 11:07:09 +0000 (12:07 +0100)
committerArvin Schnell <aschnell@suse.de>
Fri, 18 Jan 2019 11:07:09 +0000 (12:07 +0100)
package/snapper.changes
snapper/Btrfs.cc

index 652e62cf39b19f1aef3bb1599b7e582ae5aeab6e..a01e08ea8331ecf8c20196bfcd1e0e99ce1fc85f 100644 (file)
@@ -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
 
index cacc8349a9ee9ee46cbe8a59d329dd209581fef0..e54cacf167356e9a6084e8795bdbb30774bdddce 100644 (file)
@@ -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());