title: How to handle failure to release a resource which is contained in a smart pointer?
body: <p>How should an error during resource deallocation be handled, when the
  object representing the resource is contained in a shared pointer?</p>
  
  <p><strong>EDIT 1:</strong></p>
  
  <blockquote>
    <p>To put this question in more concrete terms: Many C-style interfaces
    have a function to allocate a resource, and one to release
    it. Examples are open(2) and close(2) for file descriptors on POSIX
    systems, XOpenDisplay and XCloseDisplay for a connection to an X
    server, or sqlite3_open and sqlite3_close for a connection to an
    SQLite database.</p>
    
    <p>I like to encapsulate such interfaces in a C++ class, using the Pimpl
    idiom to hide the implementation details, and providing a factory
    method returning a shared pointer to ensure that the resource is
    deallocated when no references to it remain.</p>
    
    <p>But, in all the examples given above and many others, the function
    used to release the resource may report an error. If this function is
    called by the destructor, I cannot throw an exception because
    generally destructors must not throw.</p>
    
    <p>If, on the other hand, I provide a public method to release the
    resource, I now have a class with two possible states: One in which
    the resource is valid, and one in which the resource has already been
    released. Not only does this complicate the implementation of the
    class, it also opens a potential for wrong usage. This is bad, because
    an interface should aim to make usage errors impossible.</p>
    
    <p>I would be grateful for any help with this problem.</p>
    
    <p>The original statement of the question, and thoughts about a possible
    solution follow below.</p>
  </blockquote>
  
  <p><strong>EDIT 2:</strong></p>
  
  <blockquote>
    <p>There is now a bounty on this question. A solution <em>must</em> meet these
    requirements:</p>
    
    <ol>
    <li>The resource is released if and only if no references to it remain.</li>
    <li>References to the resource may be destroyed explicitly. An exception is thrown if an error occured while releasing the resource.</li>
    <li>It is not possible to use a resource which has already been released.</li>
    <li>Reference counting and releasing of the resource are <a href="http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/shared_ptr.htm#ThreadSafety" rel="nofollow noreferrer">thread-safe</a>.</li>
    </ol>
    
    <p>A solution <em>should</em> meet these requirements:</p>
    
    <ol>
    <li>It uses the shared pointer provided by <a href="http://www.boost.org/" rel="nofollow noreferrer">boost</a>, the <a href="http://en.wikipedia.org/wiki/C%2B%2B_Technical_Report_1" rel="nofollow noreferrer">C++ Technical Report 1 (TR1)</a>, and the upcoming C++ standard, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf" rel="nofollow noreferrer">C++0x</a>.</li>
    <li>It is generic. Resource classes only need to implement how the resource is released.</li>
    </ol>
    
    <p>Thank you for your time and thoughts.</p>
  </blockquote>
  
  <p><strong>EDIT 3:</strong></p>
  
  <blockquote>
    <p>Thanks to everybody who answered my question.</p>
    
    <p><a href="https://stackoverflow.com/questions/2845183/how-to-handle-failure-to-release-a-resource-which-is-contained-in-a-smart-pointer/2900468#2900468">Alsk's answer</a> met everything asked for in the bounty, and
    was accepted. In multithreaded code, this solution would require
    a separate cleanup thread.</p>
    
    <p>I have added <a href="https://stackoverflow.com/questions/2845183/how-to-handle-failure-to-release-a-resource-which-is-contained-in-a-smart-pointer/3057897#3057897">another answer</a> where any exceptions during
    cleanup are thrown by the thread that actually used the resource,
    without need for a separate cleanup thread. If you are still
    interested in this problem (it bothered me a lot), please
    comment.</p>
  </blockquote>
  
  <p>Smart pointers are a useful tool to manage resources safely. Examples
  of such resources are memory, disk files, database connections, or
  network connections.</p>
  
  <pre><code>// open a connection to the local HTTP port
  boost::shared_ptr&lt;Socket&gt; socket = Socket::connect("localhost:80");
  </code></pre>
  
  <p>In a typical scenario, the class encapsulating the resource should be
  noncopyable and polymorphic. A good way to support this is to provide
  a factory method returning a shared pointer, and declare all
  constructors non-public. The shared pointers can now be copied from
  and assigned to freely. The object is automatically destroyed when no
  reference to it remains, and the destructor then releases the
  resource.</p>
  
  <pre><code>/** A TCP/IP connection. */
  class Socket
  {
  public:
      static boost::shared_ptr&lt;Socket&gt; connect(const std::string&amp; address);
      virtual ~Socket();
  protected:
      Socket(const std::string&amp; address);
  private:
      // not implemented
      Socket(const Socket&amp;);
      Socket&amp; operator=(const Socket&amp;);
  };
  </code></pre>
  
  <p>But there is a problem with this approach. The destructor must not
  throw, so a failure to release the resource will remain undetected.</p>
  
  <p>A common way out of this problem is to add a public method to release
  the resource.</p>
  
  <pre><code>class Socket
  {
  public:
      virtual void close(); // may throw
      // ...
  };
  </code></pre>
  
  <p>Unfortunately, this approach introduces another problem: Our objects
  may now contain resources which have already been released. This
  complicates the implementation of the resource class. Even worse, it
  makes it possible for clients of the class to use it incorrectly. The
  following example may seem far-fetched, but it is a common pitfall in
  multi-threaded code.</p>
  
  <pre><code>socket-&gt;close();
  // ...
  size_t nread = socket-&gt;read(&amp;buffer[0], buffer.size()); // wrong use!
  </code></pre>
  
  <p>Either we ensure that the resource is not released before the object
  is destroyed, thereby losing any way to deal with a failed resource
  deallocation. Or we provide a way to release the resource explicitly
  during the object's lifetime, thereby making it possible to use the
  resource class incorrectly.</p>
  
  <p>There is a way out of this dilemma. But the solution involves using a
  modified shared pointer class. These modifications are likely to be
  controversial.</p>
  
  <p>Typical shared pointer implementations, such as boost::shared_ptr,
  require that no exception be thrown when their object's destructor is
  called. Generally, no destructor should ever throw, so this is a
  reasonable requirement. These implementations also allow a custom
  deleter function to be specified, which is called in lieu of the
  destructor when no reference to the object remains. The no-throw
  requirement is extended to this custom deleter function.</p>
  
  <p>The rationale for this requirement is clear: The shared pointer's
  destructor must not throw. If the deleter function does not throw, nor
  will the shared pointer's destructor. However, the same holds for
  other member functions of the shared pointer which lead to resource
  deallocation, e.g. reset(): If resource deallocation fails, no
  exception can be thrown.</p>
  
  <p>The solution proposed here is to allow custom deleter functions to
  throw. This means that the modified shared pointer's destructor must
  catch exceptions thrown by the deleter function. On the other hand,
  member functions other than the destructor, e.g. reset(), shall not
  catch exceptions of the deleter function (and their implementation
  becomes somewhat more complicated).</p>
  
  <p>Here is the original example, using a throwing deleter function:</p>
  
  <pre><code>/** A TCP/IP connection. */
  class Socket
  {
  public:
      static SharedPtr&lt;Socket&gt; connect(const std::string&amp; address);
  protected:
      Socket(const std::string&amp; address);
      virtual Socket() { }
  private:
      struct Deleter;
  
      // not implemented
      Socket(const Socket&amp;);
      Socket&amp; operator=(const Socket&amp;);
  };
  
  struct Socket::Deleter
  {
      void operator()(Socket* socket)
      {
          // Close the connection. If an error occurs, delete the socket
          // and throw an exception.
  
          delete socket;
      }
  };
  
  SharedPtr&lt;Socket&gt; Socket::connect(const std::string&amp; address)
  {
      return SharedPtr&lt;Socket&gt;(new Socket(address), Deleter());
  }
  </code></pre>
  
  <p>We can now use reset() to free the resource explicitly. If there is
  still a reference to the resource in another thread or another part of
  the program, calling reset() will only decrement the reference
  count. If this is the last reference to the resource, the resource is
  released. If resource deallocation fails, an exception is thrown.</p>
  
  <pre><code>SharedPtr&lt;Socket&gt; socket = Socket::connect("localhost:80");
  // ...
  socket.reset();
  </code></pre>
  
  <p><strong>EDIT:</strong></p>
  
  <p>Here is a complete (but platform-dependent) implementation of the deleter:</p>
  
  <pre><code>struct Socket::Deleter
  {
      void operator()(Socket* socket)
      {
          if (close(socket-&gt;m_impl.fd) &lt; 0)
          {
              int error = errno;
              delete socket;
              throw Exception::fromErrno(error);
          }
  
          delete socket;
       }
  };
  </code></pre>