diff options
author | Chris Cleeland <chris.cleeland@gmail.com> | 2009-10-28 20:03:48 +0000 |
---|---|---|
committer | Chris Cleeland <chris.cleeland@gmail.com> | 2009-10-28 20:03:48 +0000 |
commit | c0af5c34378cbc09893fa10fb87820400ff26613 (patch) | |
tree | 29783ff2924a9fd4778e8a86dd01ddf4e1d95535 | |
parent | dd5dad0aef134db73dd99243f3465c1c3fa94498 (diff) | |
download | ATCD-c0af5c34378cbc09893fa10fb87820400ff26613.tar.gz |
Wed Oct 28 19:49:39 UTC 2009 Chris Cleeland <cleeland@ociweb.com>
* ace/Select_Reactor_Base.h:
* ace/Select_Reactor_Base.cpp:
Changed the second recv() that is used in case of a short first
read to be a recv_n(), blocking until the rest of the buffer can
be received on the pipe. The problem was discovered during
routine testing (Notify_Performance_Test) on VxWorks 6.7 on a P3
platform, but could occur on any platform. [Bugzilla 3754]
-rw-r--r-- | ACE/ChangeLog | 11 | ||||
-rw-r--r-- | ACE/ace/Select_Reactor_Base.cpp | 28 | ||||
-rw-r--r-- | ACE/ace/Select_Reactor_Base.h | 5 |
3 files changed, 41 insertions, 3 deletions
diff --git a/ACE/ChangeLog b/ACE/ChangeLog index c8258699330..2db9d44310a 100644 --- a/ACE/ChangeLog +++ b/ACE/ChangeLog @@ -1,3 +1,14 @@ +Wed Oct 28 19:49:39 UTC 2009 Chris Cleeland <cleeland@ociweb.com> + + * ace/Select_Reactor_Base.h: + * ace/Select_Reactor_Base.cpp: + + Changed the second recv() that is used in case of a short first + read to be a recv_n(), blocking until the rest of the buffer can + be received on the pipe. The problem was discovered during + routine testing (Notify_Performance_Test) on VxWorks 6.7 on a P3 + platform, but could occur on any platform. [Bugzilla 3754] + Wed Oct 28 11:58:21 UTC 2009 Olli Savia <ops@iki.fi> * ace/config-win32-msvc-7.h: diff --git a/ACE/ace/Select_Reactor_Base.cpp b/ACE/ace/Select_Reactor_Base.cpp index 771a5b49d90..7f37dc89808 100644 --- a/ACE/ace/Select_Reactor_Base.cpp +++ b/ACE/ace/Select_Reactor_Base.cpp @@ -869,6 +869,25 @@ ACE_Select_Reactor_Notify::read_notify_pipe (ACE_HANDLE handle, { ACE_TRACE ("ACE_Select_Reactor_Notify::read_notify_pipe"); + // This is kind of a weird, fragile beast. We first read with a + // regular read. The read side of this socket is non-blocking, so + // the read may end up being short. + // + // If the read is short, then we do a recv_n to insure that we block + // and read the rest of the buffer. + // + // Now, you might be tempted to say, "why don't we just replace the + // first recv with a recv_n?" I was, too. But that doesn't work + // because of how the calling code in handle_input() works. In + // handle_input, the event will only be dispatched if the return + // value from read_notify_pipe() is > 0. That means that we can't + // return zero from this func unless it's an EOF condition. + // + // Thus, the return value semantics for this are: + // -1: nothing read, fatal, unrecoverable error + // 0: nothing read at all + // 1: complete buffer read + ssize_t const n = ACE::recv (handle, (char *) &buffer, sizeof buffer); if (n > 0) @@ -882,9 +901,9 @@ ACE_Select_Reactor_Notify::read_notify_pipe (ACE_HANDLE handle, // doesn't work we're in big trouble since the input stream // won't be aligned correctly. I'm not sure quite what to // do at this point. It's probably best just to return -1. - if (ACE::recv (handle, - ((char *) &buffer) + n, - remainder) != remainder) + if (ACE::recv_n (handle, + ((char *) &buffer) + n, + remainder) != remainder) return -1; } @@ -911,6 +930,9 @@ ACE_Select_Reactor_Notify::handle_input (ACE_HANDLE handle) int result = 0; ACE_Notification_Buffer buffer; + // If there is only one buffer in the pipe, this will loop and call + // read_notify_pipe() twice. The first time will read the buffer, and + // the second will read the fact that the pipe is empty. while ((result = this->read_notify_pipe (handle, buffer)) > 0) { // Dispatch the buffer diff --git a/ACE/ace/Select_Reactor_Base.h b/ACE/ace/Select_Reactor_Base.h index 20c1e536e6a..565dd2c4afb 100644 --- a/ACE/ace/Select_Reactor_Base.h +++ b/ACE/ace/Select_Reactor_Base.h @@ -180,6 +180,11 @@ public: /// Read one of the notify call on the @a handle into the /// @a buffer. This could be because of a thread trying to unblock /// the Reactor_Impl + /// + /// Return value semantics for this are: + /// -1: nothing read, fatal, unrecoverable error + /// 0: nothing read at all + /// 1: complete buffer read virtual int read_notify_pipe (ACE_HANDLE handle, ACE_Notification_Buffer &buffer); |