Fix apple bug around TFO writes
authorSubodh Iyengar <subodh@fb.com>
Thu, 29 Sep 2016 13:42:11 +0000 (06:42 -0700)
committerFacebook Github Bot <facebook-github-bot-bot@fb.com>
Thu, 29 Sep 2016 13:53:38 +0000 (06:53 -0700)
Summary:
When using connectx to do TFO, apple has a bug
where the second write after a TFO write will cause
the socket to throw an ENOTCONN error instead of an
EAGAIN. Linux handles this case fine and returns an
EAGAIN, however apple returns ENOTCONN.

We solve this by treating ENOTCONN as an EAGAIN temporarily.

Reviewed By: yfeldblum

Differential Revision: D3942681

fbshipit-source-id: ab4f0b5fd6cdcfe9c584ea00849705a2d739d65f

folly/io/async/AsyncSocket.cpp

index beafbe5f11af0baf9109c4f4a4eb781dc55da979..bb41685dd3d3fb5a70befadf68cec62cc25d3597 100644 (file)
@@ -1870,7 +1870,15 @@ AsyncSocket::WriteResult AsyncSocket::performWrite(
   auto writeResult = sendSocketMessage(fd_, &msg, msg_flags);
   auto totalWritten = writeResult.writeReturn;
   if (totalWritten < 0) {
-    if (!writeResult.exception && errno == EAGAIN) {
+    bool tryAgain = (errno == EAGAIN);
+#ifdef __APPLE__
+    // Apple has a bug where doing a second write on a socket which we
+    // have opened with TFO causes an ENOTCONN to be thrown. However the
+    // socket is really connected, so treat ENOTCONN as a EAGAIN until
+    // this bug is fixed.
+    tryAgain |= (errno == ENOTCONN);
+#endif
+    if (!writeResult.exception && tryAgain) {
       // TCP buffer is full; we can't write any more data right now.
       *countWritten = 0;
       *partialWritten = 0;