summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Cleeland <chris.cleeland@gmail.com>2009-10-28 20:03:48 +0000
committerChris Cleeland <chris.cleeland@gmail.com>2009-10-28 20:03:48 +0000
commitc0af5c34378cbc09893fa10fb87820400ff26613 (patch)
tree29783ff2924a9fd4778e8a86dd01ddf4e1d95535
parentdd5dad0aef134db73dd99243f3465c1c3fa94498 (diff)
downloadATCD-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/ChangeLog11
-rw-r--r--ACE/ace/Select_Reactor_Base.cpp28
-rw-r--r--ACE/ace/Select_Reactor_Base.h5
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);