I think the only changes I'd make is to not make the variables in SysSemaphore public and define methods for the different operations that might change/test the state.
Rick On Fri, Feb 5, 2010 at 1:14 PM, Mark Miesfeld <miesf...@gmail.com> wrote: > 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 > ------------------------------------------------------------------------------ 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