[Ace-users] [ace-users] ACE_Select_Reactor_Handler_Repository Bug
Paul Daugherty
paul at nextalk.com
Thu Mar 6 15:47:18 CST 2008
ACE VERSION:
5.5 (Not an issue with 5.6.3 - see below)
HOST MACHINE and OPERATING SYSTEM:
Windows
TARGET MACHINE and OPERATING SYSTEM, if different from HOST:
COMPILER NAME AND VERSION (AND PATCHLEVEL):
N/A
THE $ACE_ROOT/ace/config.h FILE [if you use a link to a platform-
specific file, simply state which one]:
#if defined (WIN32)
# define ACE_HAS_MFC 1
# if defined (NXI_USE_SSL)
# define ACE_SSL_HAS_DLL 1
# define ACE_SSL_BUILD_DLL
# endif // NXI_USE_SSL
# include "ace/config-win32.h"
# if defined (ACE_HAS_WCHAR)
# undef ACE_HAS_WCHAR
# endif // ACE_HAS_WCHAR
#elif defined(linux) // WIN32
# define ACE_HAS_LINUX_EPOLL
# include "config-linux.h"
#endif // WIN32
AREA/CLASS/EXAMPLE AFFECTED:
N/A
DOES THE PROBLEM AFFECT:
The problem affects the WIN32 proactor when the notification
pipe fails to open.
The ACE_Select_Reactor_Handler_Repository has been refactored
since version 5.5; however, I am still submitting this bug in case
anybody is still using and/or supporting version 5.5.
If this is a well-known issue, then I apologize in advance.
SYNOPSIS:
ACE_Select_Reactor_Handler_Repository::bind will cause a crash
if the notification pipe's listen call fails during ACE_Proactor
construction.
DESCRIPTION:
When constructing an ACE_Proactor, The ACE_Asynch_Pseudo_Task
constructor will construct an ACE_Select_Reactor which in turn opens an
ACE_Select_Reactor_Handler_Repository and an ACE_Pipe for notifications.
On a heavily loaded system, ACE_Pipe::open fails with ENOBUFS and the
ACE_Select_Reactor will close the ACE_Select_Reactor_Handler_Repository.
This failure goes undetected since it occurs in the ACE_Proactor
constructor.
Next, when an asynch operation is issued like
ACE_Asynch_Connector::connect that does not complete immediately, the
ACE_Select_Reactor_Handler_Repository::event_handlers_ member is
eventually accessed via ACE_Select_Reactor_Handler_Repository::bind and
a crash occurs.
REPEAT BY:
This is a quick test that I wrote to ensure this is not a
problem with the 5.6.3 code (it is not):
class Bogus_Handler : public ACE_Event_Handler
{
public:
Bogus_Handler () {}
virtual ~Bogus_Handler () {}
};
int
run_main (int, ACE_TCHAR *[])
{
ACE_START_TEST (ACE_TEXT ("Paul_Daugherty_Test"));
Bogus_Handler event_handler;
ACE_Pipe notification_pipe;
ACE_Select_Reactor select_reactor;
ACE_Select_Reactor_Handler_Repository rep (select_reactor);
int ret = notification_pipe.open ();
if (0 == ret)
{
ret = rep.open (1024);
}
if (0 == ret)
{
rep.close ();
// The following causes a crash on 5.5. bind is called if
an
// asynch connect is issued and it does not complete
immediately,
// i.e. connect_i returns 0 instead of 1.
rep.bind (notification_pipe.read_handle(),
&event_handler,
ACE_Event_Handler::READ_MASK);
}
ACE_END_TEST;
return ret;
}
SAMPLE FIX/WORKAROUND:
In file Select_Reactor_Base.cpp,
ACE_Select_Reactor_Handler_Repository::bind, replace the conditional on
line 258:
else if (this->max_handlep1_ < this->max_size_)
with:
else if (this->event_handlers_ && this->max_handlep1_ <
this->max_size_)
Of course the better workaround is to upgrade to 5.6.3 which we
plan to do soon ;-)
More information about the Ace-users
mailing list