diff options
Diffstat (limited to 'third_party/libjingle')
-rw-r--r-- | third_party/libjingle/files/talk/base/physicalsocketserver.cc | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/third_party/libjingle/files/talk/base/physicalsocketserver.cc b/third_party/libjingle/files/talk/base/physicalsocketserver.cc index b05b44c..fe7da7a 100644 --- a/third_party/libjingle/files/talk/base/physicalsocketserver.cc +++ b/third_party/libjingle/files/talk/base/physicalsocketserver.cc @@ -253,6 +253,10 @@ public: // Note: on graceful shutdown, recv can return 0. In this case, we // pretend it is blocking, and then signal close, so that simplifying // assumptions can be made about Recv. + LOG(LS_WARNING) << "EOF from socket; deferring close event"; + // Must turn this back on so that the select() loop will notice the close + // event. + enabled_events_ |= kfRead; error_ = EWOULDBLOCK; return SOCKET_ERROR; } @@ -390,6 +394,7 @@ public: virtual void OnPreEvent(uint32 ff) = 0; virtual void OnEvent(uint32 ff, int err) = 0; virtual int GetDescriptor() = 0; + virtual bool IsDescriptorClosed() = 0; }; class EventDispatcher : public Dispatcher { @@ -440,6 +445,10 @@ public: return afd_[0]; } + virtual bool IsDescriptorClosed() { + return false; + } + private: PhysicalSocketServer *ss_; int afd_[2]; @@ -478,6 +487,14 @@ public: return s_; } + virtual bool IsDescriptorClosed() { + // We don't have a reliable way of distinguishing end-of-stream + // from readability. So test on each readable call. Is this + // inefficient? Probably. + char ch; + return (0 == ::recv(s_, &ch, 1, MSG_PEEK)); + } + virtual uint32 GetRequestedEvents() { return enabled_events_; } @@ -534,6 +551,10 @@ public: return fd_; } + virtual bool IsDescriptorClosed() { + return false; + } + virtual uint32 GetRequestedEvents() { return flags_; } @@ -903,7 +924,11 @@ bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) { uint32 ff = 0; if (FD_ISSET(fd, &fdsRead)) { FD_CLR(fd, &fdsRead); - ff |= kfRead; + if (pdispatcher->IsDescriptorClosed()) { + ff |= kfClose; + } else { + ff |= kfRead; + } } if (FD_ISSET(fd, &fdsWrite)) { FD_CLR(fd, &fdsWrite); |