Package: libboost1.37-dev
Version: 1.37.0-5+b1
Severity: important
Tags: upstream patch

Hi,

a lot of deluge and qbittorrent users (rdeps of libtorrent-rasterbar, which is
in turn a rdep of boost1.37) reported[0] a bug related to the asio library
included in libboost1.37-dev.

The bug is related to the following traceback (similar with both clients):

  [...]
  RuntimeError: eventfd_select_interrupter: Function not implemented

and prevents clients from starting, making the packages unusable.

It has been reported only on debian amd64 systems (debian is likely the only
distribution which actually builds libtorrent-rasterbar against boost1.37, but
I don't know if the bug affects all 64bit systems).

It has been reported upstream at:

  https://svn.boost.org/trac/boost/ticket/2683

and fixed with the following svn commit:

  https://svn.boost.org/trac/boost/changeset/50961

New boost1.38 is not affected by this bug, as mentioned in upstream changelog.

I've rebuilt boost1.37 packages applying such patch and users confirmed me it
works well.

Could you please add the following patch (quilt ready) to the official packages
so that we can fix this severe bug while waiting for boost1.38?

Thanks,
Cristian


[0] The bug has been filed on debian bts:

  http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=519036

on launchpad:

  https://bugs.launchpad.net/qbittorrent/+bug/341968

on deluge upstream support forum:

  http://forum.deluge-torrent.org/search.php?keywords=eventfd

and boost bug tracker:

  https://svn.boost.org/trac/boost/ticket/2683



-- System Information:
Debian Release: squeeze/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: i386 (i686)

Kernel: Linux 2.6.28-1-686 (SMP w/1 CPU core)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages libboost1.37-dev depends on:
ii  libboost-math1.37-dev        1.37.0-5+b1 Boost.Math Library development fil
ii  libboost-serialization1.37-d 1.37.0-5+b1 serialization library for C++
ii  libc6                        2.9-4       GNU C Library: Shared libraries
ii  libgcc1                      1:4.3.3-5   GCC support library
ii  libicu40                     4.0.1-2     International Components for Unico
ii  libstdc++6                   4.3.3-5     The GNU Standard C++ Library v3
ii  libstdc++6-4.3-dev [libstdc+ 4.3.3-5     The GNU Standard C++ Library v3 (d

Versions of packages libboost1.37-dev recommends:
ii  libboost-date-time1.37-dev   1.37.0-5+b1 set of date-time libraries based o
ii  libboost-filesystem1.37-dev  1.37.0-5+b1 filesystem operations (portable pa
pn  libboost-graph1.37-dev       <none>      (no description available)
pn  libboost-iostreams1.37-dev   <none>      (no description available)
pn  libboost-mpi1.37-dev         <none>      (no description available)
ii  libboost-program-options1.37 1.37.0-5+b1 program options library for C++
ii  libboost-python1.37-dev      1.37.0-5+b1 Boost.Python Library development f
ii  libboost-regex1.37-dev       1.37.0-5+b1 regular expression library for C++
ii  libboost-signals1.37-dev     1.37.0-5+b1 managed signals and slots library 
ii  libboost-system1.37-dev      1.37.0-5+b1 Operating system (e.g. diagnostics
pn  libboost-test1.37-dev        <none>      (no description available)
ii  libboost-thread1.37-dev      1.37.0-5+b1 portable C++ multi-threading
pn  libboost-wave1.37-dev        <none>      (no description available)
pn  libboost1.37-doc             <none>      (no description available)

libboost1.37-dev suggests no packages.

-- no debconf information
Use a pipe if eventfd is not supported at runtime.

Reported upstream as https://svn.boost.org/trac/boost/ticket/2683
Fixed upstream at https://svn.boost.org/trac/boost/changeset/50961

--- boost_1_37_0.orig/boost/asio/detail/eventfd_select_interrupter.hpp
+++ boost_1_37_0/boost/asio/detail/eventfd_select_interrupter.hpp
@@ -58,9 +58,9 @@
   eventfd_select_interrupter()
   {
 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-    read_descriptor_ = syscall(__NR_eventfd, 0);
+    write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
 #else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-    read_descriptor_ = ::eventfd(0, 0);
+    write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
 #endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
     if (read_descriptor_ != -1)
     {
@@ -68,16 +68,29 @@
     }
     else
     {
-      boost::system::error_code ec(errno,
-          boost::asio::error::get_system_category());
-      boost::system::system_error e(ec, "eventfd_select_interrupter");
-      boost::throw_exception(e);
+      int pipe_fds[2];
+      if (pipe(pipe_fds) == 0)
+      {
+        read_descriptor_ = pipe_fds[0];
+        ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+        write_descriptor_ = pipe_fds[1];
+        ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
+      }
+      else
+      {
+        boost::system::error_code ec(errno,
+            boost::asio::error::get_system_category());
+        boost::system::system_error e(ec, "eventfd_select_interrupter");
+        boost::throw_exception(e);
+      }
     }
   }
 
   // Destructor.
   ~eventfd_select_interrupter()
   {
+    if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)
+      ::close(write_descriptor_);
     if (read_descriptor_ != -1)
       ::close(read_descriptor_);
   }
@@ -86,17 +99,30 @@
   void interrupt()
   {
     uint64_t counter(1UL);
-    ::write(read_descriptor_, &counter, sizeof(uint64_t));
+    ::write(write_descriptor_, &counter, sizeof(uint64_t));
   }
 
   // Reset the select interrupt. Returns true if the call was interrupted.
   bool reset()
   {
-    // Only perform one read. The kernel maintains an atomic counter.
-    uint64_t counter(0);
-    int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
-    bool was_interrupted = (bytes_read > 0);
-    return was_interrupted;
+    if (write_descriptor_ == read_descriptor_)
+    {
+      // Only perform one read. The kernel maintains an atomic counter.
+      uint64_t counter(0);
+      int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
+      bool was_interrupted = (bytes_read > 0);
+      return was_interrupted;
+    }
+    else
+    {
+      // Clear all data from the pipe.
+      char data[1024];
+      int bytes_read = ::read(read_descriptor_, data, sizeof(data));
+      bool was_interrupted = (bytes_read > 0);
+      while (bytes_read == sizeof(data))
+        bytes_read = ::read(read_descriptor_, data, sizeof(data));
+      return was_interrupted;
+    }
   }
 
   // Get the read descriptor to be passed to select.
@@ -111,6 +137,12 @@
   // 64bit value will be written on the other end of the connection and this
   // descriptor will become readable.
   int read_descriptor_;
+
+  // The write end of a connection used to interrupt the select call. A single
+  // 64bit non-zero value may be written to this to wake up the select which is
+  // waiting for the other end to become readable. This descriptor will only
+  // differ from the read descriptor when a pipe is used.
+  int write_descriptor_;
 };
 
 } // namespace detail

Attachment: signature.asc
Description: Digital signature

Reply via email to