[Ace-users] [ace-users] ACE_Asynch_Acceptor: Cancellation Bug

Steve Huston shuston at riverace.com
Mon Feb 25 17:39:17 CST 2008


Hi Paul,

Thanks for the thorough research and report. Could you please do one
of the following:

1. Check ACE 5.6.3 to see if the problem remains there. If so, please
report this in Bugzilla.
2. Take advantage of Riverace support which can integrate and test
this in an ACE 5.5 fix kit.

Best regards,
-Steve

--
Steve Huston, Riverace Corporation
Want to take ACE training on YOUR schedule?
See http://www.riverace.com/training.htm


> -----Original Message-----
> From: ace-users-bounces at cse.wustl.edu 
> [mailto:ace-users-bounces at cse.wustl.edu] On Behalf Of Paul Daugherty
> Sent: Monday, February 25, 2008 6:22 PM
> To: ace-users at cs.wustl.edu
> Subject: [ace-users] ACE_Asynch_Acceptor: Cancellation Bug
> 
> 
>     ACE VERSION: 
> 
>         5.5
> 
>     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 is with the ACE_Asynch_Acceptor interface and
will
> affect execution on Windows when shutting down an 
> ACE_Asynch_Acceptor.  
> 
>     SYNOPSIS:
> 
>         Cancelling an acceptor from a different thread from 
> which open()
> was called is troublesome due to the following:
> 
>         1) The ACE_Asynch_Acceptor interface for the handle()
methods
> are as follows:
> 
>         /// Return the listen handle.
>         ACE_HANDLE handle (void) const;
>         /// Set the listen handle.
>         void handle (ACE_HANDLE h);	
> 
>         However, after inspecting the implemenation for the handle
> setter, it appears that the setter method does not set the listen
> handle, instead it calls ACE_Handler::handle(ACE_HANDLE).
> 
>         2) The ACE_Asynch_Acceptor handle() methods are protected
and
> should be public.
> 
>     DESCRIPTION:
> 
>         On Win32, it is well known that the 
> ACE_Asynch_Acceptor::cancel
> method will only cancel outstanding accepts if cancel is 
> called from the
> same thread that accepts were called from.  Because of this, the
only
> way to cancel the outstanding reads (accepts) on the acceptor from a
> different thread is to call ACE_OS::closesocket on the acceptor's
> listen_handle_.  After all i/o operations complete, the 
> acceptor can be
> safely destroyed.
> 
>         When closesocket is called on the acceptor's 
> listen_handle_, the
> acceptor's listen handle must be assigned ACE_INVALID_HANDLE 
> or the same
> handle will be closed in the acceptor's dtor which could 'pull the
rug
> out from under' another newly created and unrelated socket.
> 
>         The current interface provides a set_handle() method 
> which does
> assign a value to listen_handle_ but this method allocates a new
> implementation which will cause a memory leak of the old 
> implementation
> allocation.
> 
>         So, unless somebody enlightens me to a better way, the way
to
> cancel/shutdown an ACE_Asynch_Acceptor from a different thread is as
> follows:
> 
>         // closesocket req'd since we're closing from different
thread
> than 
>         // thread where i/o was issued.
>         1) ACE_OS::closesocket(acceptor->handle()); // or
> acceptor->get_handle()
>         2) acceptor->handle(ACE_INVALID_HANDLE);
>         3) Wait for all outstanding i/o to complete
>         4) Delete the acceptor
> 
>         The acceptor does have a public cancel() method but as
stated
> above, it does not work when called from a different thread than the
> thread cancel() is called in.
> 
>         ACE_Asynch_Acceptor::handle(ACE_HANDLE h) has a 
> comment stating
> that '/// Set the listen handle' but it does not set the 
> listen handle,
> it calls "ACE_Handler::handle(h)."
> 
>         The ACE_Asynch_Acceptor::handle() methods must have
protected
> access but need to have public access since these methods are 
> part of an
> acceptor's cancellation due to the inter-thread ineffectiveness of
the
> cancel() method.
> 
>     REPEAT BY:
> 
>         N/A
> 
>     SAMPLE FIX/WORKAROUND:
> 
>         1) Change the 'void handle(ACE_HANDLE h)' method as follows:
> 
>             template <class HANDLER> void
>             ACE_Asynch_Acceptor<HANDLER>::handle (ACE_HANDLE h)
>               {
>                 --ACE_Handler::handle (h);
>                 ++this->listen_handle_ = h;
>               }
> 
>         2) Change access to the handle() methods from protected to
> public.
> 
> _______________________________________________
> ace-users mailing list
> ace-users at mail.cse.wustl.edu
> http://mail.cse.wustl.edu/mailman/listinfo/ace-users
> 




More information about the Ace-users mailing list