On Fri, Feb 5, 2010 at 2:00 AM, Rick McGuire <object.r...@gmail.com> wrote:
> This actually looks better, but I suspect that the hang is now > occurring because the reentrant windows proc is creating a condition > where this thread is never getting a chance to be woken up. I didn't > really expect this chance to make the oodialog problem go way, but > rather to keep the internal interpreter state from getting corrupted. Rick, Yes, the call stacks I looked at did not look as corrupted as they did before. Below is the thread local storage change that fixes the ooDialog problem for you to review. (Well along with the change to relinquish() in Windows that I committed last night.) * It is confined to Windows dependent files. * It reuses the old RexxSetProcessMessages() API. It would have been cleaner, I think, to put the global vaiables needed in SystemInterpreter. But, since SysSemaphore is linked into rxapi.dll and rexxapi.exe, the convultions needed to get it to compile were just too much. I've tested it yesterday and today, including running the test suite with and don't see any problems. Index: interpreter/platform/windows/MiscSystem.cpp =================================================================== --- interpreter/platform/windows/MiscSystem.cpp (revision 5539) +++ interpreter/platform/windows/MiscSystem.cpp (working copy) @@ -200,12 +200,19 @@ /** * This was an undocumented API prior to 4.0, but is known to have been used by - * some IBM applications. This is maintained solely for binary compatibility. + * some IBM applications. Therefore this was maintained solely for binary + * compatibility. * + * <new doc TBD> + * * @return TRUE always. */ -BOOL APIENTRY RexxSetProcessMessages(BOOL onoff) +BOOL APIENTRY RexxSetProcessMessages(BOOL turnOn) { - return TRUE; + if ( ! turnOn ) + { + TlsSetValue(SysSemaphore::tlsNoMessageLoopIndex, (LPVOID)1); + } + return TRUE; } Index: interpreter/platform/windows/SystemInitialization.cpp =================================================================== --- interpreter/platform/windows/SystemInitialization.cpp (revision 5539) +++ interpreter/platform/windows/SystemInitialization.cpp (working copy) @@ -44,6 +44,7 @@ #include <stdlib.h> /* Get system, max_path etc... */ #include "RexxCore.h" #include "SystemInterpreter.hpp" +#include "SysSemaphore.hpp" /* */ @@ -74,12 +75,23 @@ { if (fdwReason == DLL_PROCESS_ATTACH) { + // Allocate a thread local storage index + SysSemaphore::tlsNoMessageLoopIndex = TlsAlloc(); + if (SysSemaphore::tlsNoMessageLoopIndex == TLS_OUT_OF_INDEXES) + { + return FALSE; + } + SysSemaphore::usingTls = true; + // perform the interpreter start up SystemInterpreter::processStartup(hinstDll); } else if (fdwReason == DLL_PROCESS_DETACH) { SystemInterpreter::processShutdown(); + + // Free the thread local storage index + TlsFree(SysSemaphore::tlsNoMessageLoopIndex); } return TRUE; } Index: common/platform/windows/SysSemaphore.cpp =================================================================== --- common/platform/windows/SysSemaphore.cpp (revision 5539) +++ common/platform/windows/SysSemaphore.cpp (working copy) @@ -44,6 +44,9 @@ #include "SysSemaphore.hpp" +bool SysSemaphore::usingTls = false; +DWORD SysSemaphore::tlsNoMessageLoopIndex = 0; + /** * Create a semaphore with potential creation-time * initialization. Index: common/platform/windows/SysSemaphore.hpp =================================================================== --- common/platform/windows/SysSemaphore.hpp (revision 5539) +++ common/platform/windows/SysSemaphore.hpp (working copy) @@ -49,46 +49,8 @@ #include <stdlib.h> -inline void waitHandle(HANDLE s) -{ - MSG msg = {0}; +inline void waitHandle(HANDLE s); - // If already signaled, return. - if ( WaitForSingleObject(s, 0) == WAIT_OBJECT_0 ) - { - return; - } - - /** Any thread that creates windows must process messages. A thread that - * calls WaitForSingelObject with an infinite timeout risks deadlocking the - * system. MS's solution for this is to use MsgWaitForMultipleObjects to - * wait on the object, or a new message arriving in the message queue. Some - * threads create windows indirectly, an example is COM with CoInitialize. - * Since we can't know if the current thread has a message queue that needs - * processing, we use MsgWaitForMultipleObjects. - * - * Note that MsgWaitForMultipleObjects only returns if a new message is - * placed in the queue. PeekMessage alters the state of all messages in - * the queue so that they are no longer 'new.' Once PeekMessage is called, - * all the messages on the queue need to be processed. - */ - do - { - while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - - // Check to see if signaled. - if ( WaitForSingleObject(s, 0) == WAIT_OBJECT_0 ) - { - return; - } - } - } while ( MsgWaitForMultipleObjects(1, &s, FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0 + 1 ); -} - - class SysSemaphore { public: SysSemaphore() : sem(0) { ; } @@ -111,6 +73,9 @@ inline void reset() { ResetEvent(sem); } inline bool posted() { return WaitForSingleObject(sem, 0) != 0; } + static bool usingTls; + static DWORD tlsNoMessageLoopIndex; + protected: HANDLE sem; }; @@ -141,4 +106,69 @@ protected: HANDLE mutexMutex; // the actual mutex }; + + +/** + * Wait for a synchronization object to be in the signaled state. + * + * Any thread that creates windows must process messages. A thread that + * calls WaitForSingelObject with an infinite timeout risks deadlocking the + * system. MS's solution for this is to use MsgWaitForMultipleObjects to + * wait on the object, or a new message arriving in the message queue. Some + * threads create windows indirectly, an example is COM with CoInitialize. + * Since we can't know if the current thread has a message queue that needs + * processing, we use MsgWaitForMultipleObjects. + * + * However, with the introduction of the C++ native API in ooRexx 4.0.0, it + * became possible for external native libraries to attach to a thread with an + * active window procedure. If a wait is done on that thread, here, + * PeekMessage() causes non-queued messages to be dispatched, and the window + * procedure is reentered. This can cause the Rexx program to hang. In + * addition, in the one known extension where this problem happens, ooDialog, + * the messages need to be passed to the dialog manager rather than dispatched + * directly to the window. + * + * For this special case, the thread can explicity ask, (through + * RexxSetProcessMessages,) that messages are *not* processed during this wait. + * Thread local storage is used to keep track of a flag signalling this case. + * + * Note that MsgWaitForMultipleObjects only returns if a new message is + * placed in the queue. PeekMessage alters the state of all messages in + * the queue so that they are no longer 'new.' Once PeekMessage is called, + * all the messages on the queue need to be processed. + */ +inline void waitHandle(HANDLE s) +{ + // If already signaled, return. + if ( WaitForSingleObject(s, 0) == WAIT_OBJECT_0 ) + { + return; + } + + // If using thread local storage and no message loop is flagged, then use WaitForSingleobject() + if ( SysSemaphore::usingTls && (DWORD_PTR)TlsGetValue(SysSemaphore::tlsNoMessageLoopIndex) == 1 ) + { + WaitForSingleObject(s, INFINITE); + return; + } + + MSG msg = {0}; + + do + { + while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + + // Check to see if signaled. + if ( WaitForSingleObject(s, 0) == WAIT_OBJECT_0 ) + { + return; + } + } + } while ( MsgWaitForMultipleObjects(1, &s, FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0 + 1 ); +} + + #endif ------------------------------------------------------------------------------ The Planet: dedicated and managed hosting, cloud storage, colocation Stay online with enterprise data centers and the best network in the business Choose flexible plans and management services without long-term contracts Personal 24x7 support from experience hosting pros just a phone call away. http://p.sf.net/sfu/theplanet-com _______________________________________________ Oorexx-devel mailing list Oorexx-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/oorexx-devel