RE: [Quickfix-developers] Incorrect threading function.
Brought to you by:
orenmnero
From: Daniel M. <Dan...@ma...> - 2003-11-26 12:37:03
|
I have fixed the issues below, and will check them in after I do some more testing. Please comment on any possible side effects these changes may have. 1. I found the documentation that warns against using _beginthread with synchronization API's:=20 =20 "The _beginthreadex function gives you more control over how the thread is created than _beginthread does. The _endthreadex function is also more flexible. For example, with _beginthreadex, you can use security information, set the initial state of the thread (running or suspended), and get the thread identifier of the newly created thread. You are also able to use the thread handle returned by _beginthreadex with the synchronization APIs, which you cannot do with _beginthread.=20 It is safer to use _beginthreadex than _beginthread. If the thread spawned by _beginthread exits quickly, the handle returned to the caller of _beginthread may be invalid or, worse, point to another thread. However, the handle returned by _beginthreadex has to be closed by the caller of _beginthreadex, so it is guaranteed to be a valid handle if _beginthreadex did not return an error. " Since _beginthread had a different prototype for the function being spawned than _beginthreadex does, I defined the following: #ifdef _MSC_VER typedef unsigned int (_stdcall THREAD_START_ROUTINE)(void *); #define THREAD_PROC unsigned int _stdcall=20 #else typedef void * (THREAD_START_ROUTINE)(void *); #define THREAD_PROC void * #endif bool thread_spawn( THREAD_START_ROUTINE func, void* var, unsigned& thread ); bool thread_spawn( THREAD_START_ROUTINE, void* var ); I then changed the return type of the thread functions from void * to THREAD_PROC . This way only the Windows code is actually changed. 2. I saw the potential problem for the race condition, but did not have an elegant solution. Here is what I did as a work around: void SocketAcceptor::onStart() { QF_STACK_PUSH(SocketAcceptor::onStart) m_running =3D true; while ( !m_stop && m_pServer && m_pServer->block( *this ) ) {} m_running =3D false; QF_STACK_POP } void SocketAcceptor::onStop() { QF_STACK_PUSH(SocketAcceptor::onStop) m_stop =3D true; while(m_running) process_sleep(0); if ( m_pServer )=20 { m_pServer->close();=20 delete m_pServer; } QF_STACK_POP } 3. I changed GetCurrentThread() to GetCurrentThreadId(). Daniel May =20 -----Original Message----- From: Timothy Yates [mailto:ty...@pa...]=20 Sent: Friday, November 21, 2003 9:50 AM To: Daniel May Subject: RE: [Quickfix-developers] Incorrect threading function. I am not a registered quickfix developer, so the answer is no. I just thought you guys might want to know about some problems I've found. -----Original Message----- From: Daniel May [mailto:Dan...@ma...] Sent: Friday, November 21, 2003 5:39 AM To: qui...@li... Cc: ty...@pa... Subject: RE: [Quickfix-developers] Incorrect threading function. Tim, Have you checked these changes into CVS ? Daniel May da...@ma... --__--__-- Message: 2 From: Timothy Yates <ty...@pa...> To: "'qui...@li...'" <qui...@li...> Date: Thu, 20 Nov 2003 16:06:58 -0000 Subject: [Quickfix-developers] Incorrect threading function. I am using the Java quickfix API and running on a fast (3GHz) processor on Windows XP. I have encountered a number of threading problems. 1. It is quite common for QuickFIX to lock up in Acceptor.stop(). The lock-up occurs due to incorrect implementation of thread_spawn/thread_join. These should use _beginthreadex, not _beginthread. In the current implementation (using _beginthread), the call too WaitForSingleObject() generally fails because the handle it is waiting for has already been closed automatically by _beginthread. Sometimes, WaitForSingleObject() blocks indefinitely even though the acceptor thread has exited. This may be because it is waiting on an incorrect handle for which no event is likely to be signalled. In any case, the Windows documentation advises against using _beginthread and WaitForSingleObject together. 2. When stopping a SocketAcceptor there is a race condition between completion of the acceptor thread function and destruction of the SocketServer object. Since the thread function uses the SocketServer object, it should not be destroyed until the thread function has completed. I'm not sure that this is causing problems, but it looks dangerous. 3. The stack trace facility (QF_STACK_PUSH/QF_STACK_POP) does not work on Windows. This is due to incorrect implementation of thread_self(). GetCurrentThread() returns a pseudo handle, which seems to be the same irrespective of thread. I replaced this with a call to GetCurrentThreadId(). Tim Yates Lead Developer Patsystems (US) LLC 141 West Jackson Boulevard Chicago 60604, USA Tel +1 (312) 542-1336 www.patsystems.com=20 DISCLAIMER: This e-mail is confidential and may also be legally privileged. If you are not the intended recipient, use of the information contained in this e-mail (including disclosure, copying or distribution) is prohibited and may be unlawful. Please inform the sender and delete the message immediately from your system. This e-mail is attributed to the sender and may not necessarily reflect the views of the Patsystems Group and no member of the Patsystems Group accepts any liability for any action taken in reliance on the contents of this e-mail (other than where it has a legal or regulatory obligation to do so) or for the consequences of any computer viruses which may have been transmitted by this e-mail. The Patsystems Group comprises Patsystems plc and its subsidiary group of companies. --__--__-- _______________________________________________ Quickfix-developers mailing list Qui...@li... https://lists.sourceforge.net/lists/listinfo/quickfix-developers End of Quickfix-developers Digest DISCLAIMER: This e-mail is confidential and may also be legally privileged. If you are not the intended recipient, use of the information contained in this e-mail (including disclosure, copying or distribution) is prohibited and may be unlawful. Please inform the sender and delete the message immediately from your system. This e-mail is attributed to the sender and may not necessarily reflect the views of the Patsystems Group and no member of the Patsystems Group accepts any liability for any action taken in reliance on the contents of this e-mail (other than where it has a legal or regulatory obligation to do so) or for the consequences of any computer viruses which may have been transmitted by this e-mail. The Patsystems Group comprises Patsystems plc and its subsidiary group of companies. |