diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+# Version 0.4.0.0
+
+* Do not handle “Broken Pipe” errors on the `*Write*D` proxies anymore.
+  As as a result, those proxies run forever and have a polymorphic
+  return value, which makes this release binary compatible with 0.2.0.0,
+  but not with 0.3.0.0.
+
+
 # Version 0.3.0.0
 
 * Quietly stop writing or reading bytes from a TCP socket if a
diff --git a/PEOPLE b/PEOPLE
--- a/PEOPLE
+++ b/PEOPLE
@@ -5,3 +5,4 @@
 Renzo Carbonara
 Gabriel Gonzalez
 Paolo Capriotti
+Marius Ghita
diff --git a/pipes-network.cabal b/pipes-network.cabal
--- a/pipes-network.cabal
+++ b/pipes-network.cabal
@@ -1,5 +1,5 @@
 name:               pipes-network
-version:            0.3.0.0
+version:            0.4.0.0
 license:            BSD3
 license-file:       LICENSE
 copyright:          Copyright (c) Renzo Carbonara 2012-2013, Paolo Capriotti 2012-2012.
diff --git a/src/Control/Proxy/Network/Internal.hs b/src/Control/Proxy/Network/Internal.hs
--- a/src/Control/Proxy/Network/Internal.hs
+++ b/src/Control/Proxy/Network/Internal.hs
@@ -43,12 +43,6 @@
 {-# INLINE recv #-}
 
 -- | Writes the given bytes to the socket.
---
--- Returns `False` if the remote end closed the connection (“Broken Pipe”),
--- otherwise `True`.
-send :: NS.Socket -> B.ByteString -> IO Bool
-send sock bs =
-    E.handle (\Eg.IOError{Eg.ioe_type=Eg.ResourceVanished} -> return False)
-             (do Network.Socket.ByteString.sendAll sock bs
-                 return True)
+send :: NS.Socket -> B.ByteString -> IO ()
+send = Network.Socket.ByteString.sendAll
 {-# INLINE send #-}
diff --git a/src/Control/Proxy/TCP.hs b/src/Control/Proxy/TCP.hs
--- a/src/Control/Proxy/TCP.hs
+++ b/src/Control/Proxy/TCP.hs
@@ -40,7 +40,6 @@
   , Timeout(..)
   ) where
 
-import           Control.Monad
 import           Control.Monad.Trans.Class
 import qualified Control.Proxy                  as P
 import qualified Control.Proxy.Trans.Either     as PE
@@ -90,7 +89,8 @@
 --
 -- Less than the specified maximum number of bytes might be received at once.
 --
--- If the remote peer closes its side of the connection, this proxy returns.
+-- This proxy returns if the remote peer closes its side of the connection or
+-- EOF is received.
 socketReadS
   :: P.Proxy p
   => Int                -- ^Maximum number of bytes to receive and send
@@ -125,17 +125,15 @@
 -- such same bytes downstream.
 --
 -- Requests from downstream are forwarded upstream.
---
--- If the remote peer closes its side of the connection, this proxy returns.
 socketWriteD
   :: P.Proxy p
   => NS.Socket          -- ^Connected socket.
-  -> x -> p x B.ByteString x B.ByteString IO ()
+  -> x -> p x B.ByteString x B.ByteString IO r
 socketWriteD sock = P.runIdentityK loop where
     loop x = do
       a <- P.request x
-      ok <- lift (send sock a)
-      when ok (P.respond a >>= loop)
+      lift (send sock a)
+      P.respond a >>= loop
 {-# INLINABLE socketWriteD #-}
 
 --------------------------------------------------------------------------------
@@ -192,15 +190,14 @@
   :: P.Proxy p
   => Int                -- ^Timeout in microseconds (1/10^6 seconds).
   -> NS.Socket          -- ^Connected socket.
-  -> x -> (PE.EitherP Timeout p) x B.ByteString x B.ByteString IO ()
+  -> x -> (PE.EitherP Timeout p) x B.ByteString x B.ByteString IO r
 socketWriteTimeoutD wait sock = loop where
     loop x = do
       a <- P.request x
-      mt <- lift (timeout wait (send sock a))
-      case mt of
-        Just True  -> P.respond a >>= loop
-        Just False -> return ()
-        Nothing    -> PE.throw ex
+      m <- lift (timeout wait (send sock a))
+      case m of
+        Just () -> P.respond a >>= loop
+        Nothing -> PE.throw ex
     ex = Timeout $ "socketWriteTimeoutD: " <> show wait <> " microseconds."
 {-# INLINABLE socketWriteTimeoutD #-}
 
diff --git a/src/Control/Proxy/TCP/Safe.hs b/src/Control/Proxy/TCP/Safe.hs
--- a/src/Control/Proxy/TCP/Safe.hs
+++ b/src/Control/Proxy/TCP/Safe.hs
@@ -139,8 +139,6 @@
 --
 -- The connection socket is closed when done or in case of exceptions.
 --
--- If the remote peer closes its side of the connection, this proxy returns.
---
 -- Using this proxy you can write straightforward code like the following, which
 -- greets a TCP client listening locally at port 9000:
 --
@@ -151,7 +149,7 @@
   => Maybe Int          -- ^Optional timeout in microseconds (1/10^6 seconds).
   -> NS.HostName        -- ^Server host name.
   -> NS.ServiceName     -- ^Server service port.
-  -> x -> (P.ExceptionP p) x B.ByteString x B.ByteString P.SafeIO ()
+  -> x -> (P.ExceptionP p) x B.ByteString x B.ByteString P.SafeIO r
 connectWriteD mwait hp port x = do
    connect id hp port $ \(csock,_) ->
      socketWriteD mwait csock x
@@ -283,7 +281,8 @@
 --
 -- Less than the specified maximum number of bytes might be received at once.
 --
--- If the remote peer closes its side of the connection, this proxy returns.
+-- This proxy returns if the remote peer closes its side of the connection or
+-- EOF is received.
 --
 -- Both the listening and connection sockets are closed when done or in case of
 -- exceptions.
@@ -332,7 +331,7 @@
   => Maybe Int          -- ^Optional timeout in microseconds (1/10^6 seconds).
   -> S.HostPreference   -- ^Preferred host to bind.
   -> NS.ServiceName     -- ^Service port to bind.
-  -> x -> (P.ExceptionP p) x B.ByteString x B.ByteString P.SafeIO ()
+  -> x -> (P.ExceptionP p) x B.ByteString x B.ByteString P.SafeIO r
 serveWriteD mwait hp port x = do
    listen id hp port $ \(lsock,_) -> do
      accept id lsock $ \(csock,_) -> do
@@ -355,7 +354,8 @@
 --
 -- Less than the specified maximum number of bytes might be received at once.
 --
--- If the remote peer closes its side of the connection, this proxy returns.
+-- This proxy returns if the remote peer closes its side of the connection or
+-- EOF is received.
 socketReadS
   :: P.Proxy p
   => Maybe Int          -- ^Optional timeout in microseconds (1/10^6 seconds).
@@ -412,26 +412,23 @@
 -- 'P.ExceptionP' proxy transformer.
 --
 -- Requests from downstream are forwarded upstream.
---
--- If the remote peer closes its side of the connection, this proxy returns.
 socketWriteD
   :: P.Proxy p
   => Maybe Int          -- ^Optional timeout in microseconds (1/10^6 seconds).
   -> NS.Socket          -- ^Connected socket.
-  -> x -> (P.ExceptionP p) x B.ByteString x B.ByteString P.SafeIO ()
+  -> x -> (P.ExceptionP p) x B.ByteString x B.ByteString P.SafeIO r
 socketWriteD Nothing sock = loop where
     loop x = do
       a <- P.request x
-      ok <- P.tryIO (send sock a)
-      when ok (P.respond a >>= loop)
+      P.tryIO (send sock a)
+      P.respond a >>= loop
 socketWriteD (Just wait) sock = loop where
     loop x = do
       a <- P.request x
-      mok <- P.tryIO (timeout wait (send sock a))
-      case mok of
-        Just True  -> P.respond a >>= loop
-        Just False -> return ()
-        Nothing    -> P.throw ex
+      m <- P.tryIO (timeout wait (send sock a))
+      case m of
+        Just () -> P.respond a >>= loop
+        Nothing -> P.throw ex
     ex = Timeout $ "socketWriteD: " <> show wait <> " microseconds."
 {-# INLINABLE socketWriteD #-}
 
diff --git a/src/Control/Proxy/TCP/Safe/Sync.hs b/src/Control/Proxy/TCP/Safe/Sync.hs
--- a/src/Control/Proxy/TCP/Safe/Sync.hs
+++ b/src/Control/Proxy/TCP/Safe/Sync.hs
@@ -19,10 +19,9 @@
   Response(..),
   ) where
 
-import           Control.Monad
 import qualified Control.Proxy                    as P
-import           Control.Proxy.TCP.Sync
-                    (Request(..), Response(..), syncDelimit)
+import           Control.Proxy.TCP.Sync           (Request(..), Response(..),
+                                                   syncDelimit)
 import           Control.Proxy.Network.Internal
 import qualified Control.Proxy.Safe               as P
 import qualified Data.ByteString                  as B
@@ -45,7 +44,8 @@
 -- take more time that such timeout, then throw a 'Timeout' exception in
 -- the 'P.ExceptionP' proxy transformer.
 --
--- If the remote peer closes its side of the connection, this proxy returns.
+-- This proxy returns if EOF is received or the remote end closes its side of
+-- the connection while we are trying to read from it.
 socketSyncServer
   :: P.Proxy p
   => Maybe Int          -- ^Optional timeout in microseconds (1/10^6 seconds).
@@ -54,8 +54,8 @@
   -> P.Server (P.ExceptionP p) (Request B.ByteString) Response P.SafeIO ()
 socketSyncServer Nothing sock = loop where
     loop (Send bs) = do
-        ok <- P.tryIO (send sock bs)
-        when ok (P.respond Sent >>= loop)
+        P.tryIO (send sock bs)
+        P.respond Sent >>= loop
     loop (Receive nbytes) = do
         mbs <- P.tryIO (recv sock nbytes)
         case mbs of
@@ -63,11 +63,10 @@
           Nothing -> return ()
 socketSyncServer (Just wait) sock = loop where
     loop (Send bs) = do
-        mok <- P.tryIO (timeout wait (send sock bs))
-        case mok of
-          Just True  -> P.respond Sent >>= loop
-          Just False -> return ()
-          Nothing    -> P.throw ex
+        m <- P.tryIO (timeout wait (send sock bs))
+        case m of
+          Just () -> P.respond Sent >>= loop
+          Nothing -> P.throw ex
     loop (Receive nbytes) = do
         mmbs <- P.tryIO (timeout wait (recv sock nbytes))
         case mmbs of
@@ -93,7 +92,8 @@
 -- take more time that such timeout, then throw a 'Timeout' exception in
 -- the 'P.ExceptionP' proxy transformer.
 --
--- If the remote peer closes its side of the connection, this proxy returns.
+-- This proxy returns if EOF is received or the remote end closes its side of
+-- the connection while we are trying to read from it.
 socketSyncProxy
   :: P.Proxy p
   => Maybe Int          -- ^Optional timeout in microseconds (1/10^6 seconds).
@@ -102,8 +102,8 @@
   -> (P.ExceptionP p) a' B.ByteString (Request a') Response P.SafeIO ()
 socketSyncProxy Nothing sock = loop where
     loop (Send a') = do
-        ok <- P.tryIO . send sock =<< P.request a'
-        when ok (P.respond Sent >>= loop)
+        P.tryIO . send sock =<< P.request a'
+        P.respond Sent >>= loop
     loop (Receive nbytes) = do
         mbs <- P.tryIO (recv sock nbytes)
         case mbs of
@@ -111,12 +111,10 @@
           Nothing -> return ()
 socketSyncProxy (Just wait) sock = loop where
     loop (Send a') = do
-        bs <- P.request a'
-        mok <- P.tryIO (timeout wait (send sock bs))
-        case mok of
-          Just True  -> P.respond Sent >>= loop
-          Just False -> return ()
-          Nothing    -> P.throw ex
+        m <- P.tryIO . timeout wait . send sock =<< P.request a'
+        case m of
+          Just () -> P.respond Sent >>= loop
+          Nothing -> P.throw ex
     loop (Receive nbytes) = do
         mmbs <- P.tryIO (timeout wait (recv sock nbytes))
         case mmbs of
diff --git a/src/Control/Proxy/TCP/Sync.hs b/src/Control/Proxy/TCP/Sync.hs
--- a/src/Control/Proxy/TCP/Sync.hs
+++ b/src/Control/Proxy/TCP/Sync.hs
@@ -26,7 +26,6 @@
   Response(..),
   ) where
 
-import           Control.Monad
 import           Control.Monad.Trans.Class
 import qualified Control.Proxy                    as P
 import           Control.Proxy.Network.Internal
@@ -57,7 +56,8 @@
 -- bytes as @'Received' bytes@. Less than the specified maximum number of bytes
 -- might be received at once.
 --
--- If the remote peer closes its side of the connection, this proxy returns.
+-- This proxy returns if EOF is received or the remote end closes its side of
+-- the connection while we are trying to read from it.
 socketSyncServer
   :: P.Proxy p
   => NS.Socket          -- ^Connected socket.
@@ -65,8 +65,8 @@
   -> P.Server p (Request B.ByteString) Response IO ()
 socketSyncServer sock = P.runIdentityK loop where
     loop (Send bs) = do
-        ok <- lift (send sock bs)
-        when ok (P.respond Sent >>= loop)
+        lift (send sock bs)
+        P.respond Sent >>= loop
     loop (Receive nbytes) = do
         mbs <- lift (recv sock nbytes)
         case mbs of
@@ -86,7 +86,8 @@
 -- bytes as @'Received' bytes@. Less than the specified maximum number of bytes
 -- might be received at once.
 --
--- If the remote peer closes its side of the connection, this proxy returns.
+-- This proxy returns if EOF is received or the remote end closes its side of
+-- the connection while we are trying to read from it.
 socketSyncProxy
   :: P.Proxy p
   => NS.Socket          -- ^Connected socket.
@@ -94,8 +95,8 @@
   -> p a' B.ByteString (Request a') Response IO ()
 socketSyncProxy sock = P.runIdentityK loop where
     loop (Send a') = do
-        ok <- lift . send sock =<< P.request a'
-        when ok (P.respond Sent >>= loop)
+        lift . send sock =<< P.request a'
+        P.respond Sent >>= loop
     loop (Receive nbytes) = do
         mbs <- lift (recv sock nbytes)
         case mbs of
@@ -121,11 +122,10 @@
   -> P.Server (PE.EitherP Timeout p) (Request B.ByteString) Response IO ()
 socketSyncServerTimeout wait sock = loop where
     loop (Send bs) = do
-        mok <- lift (timeout wait (send sock bs))
-        case mok of
-          Just True  -> P.respond Sent >>= loop
-          Just False -> return ()
-          Nothing    -> PE.throw ex
+        m <- lift (timeout wait (send sock bs))
+        case m of
+          Just () -> P.respond Sent >>= loop
+          Nothing -> PE.throw ex
     loop (Receive nbytes) = do
         mmbs <- lift (timeout wait (recv sock nbytes))
         case mmbs of
@@ -146,11 +146,10 @@
   -> (PE.EitherP Timeout p) a' B.ByteString (Request a') Response IO ()
 socketSyncProxyTimeout wait sock = loop where
     loop (Send a') = do
-        mok <- lift . timeout wait . send sock =<< P.request a'
-        case mok of
-          Just True  -> P.respond Sent >>= loop
-          Just False -> return ()
-          Nothing    -> PE.throw ex
+        m <- lift . timeout wait . send sock =<< P.request a'
+        case m of
+          Just () -> P.respond Sent >>= loop
+          Nothing -> PE.throw ex
     loop (Receive nbytes) = do
         mmbs <- lift (timeout wait (recv sock nbytes))
         case mmbs of
