On Fri Dec 17 19:11:29 2004, cbecker wrote: > This is a bug report for perl from chris@fatorange.com, > generated with the help of perlbug 1.35 running under perl v5.8.5. > > > ----------------------------------------------------------------- > win32_msgwait will loop forever under the condition that none of the handles > becomes ready, while MsgWaitForMultipleObjects keeps on returning events > before the timeout (non-infinite) is ever hit. > Just ran into this (timeout: 1 second) and had a debugger handy - looking at > the source, this should be fairly easy to understand & recreate. The > solution would be to decrease the timeout by the amount waited with every > run - watch out for DWORD overflows! Looking at http://perl5.git.perl.org/perl.git/blob/eb92badec069d2041ebf51c3654ed7e62e7309e9:/win32/win32.c#l2154 . There is a wall time check and the timer is decreased (actually increased towards expire time) correctly but there is a race with a deadlock (near infinity timeout) if the delay from MsgWaitForMultipleObjects to GetTickCount exceeds 1 ms causing var ticks to go > var timeout. For "while MsgWaitForMultipleObjects keeps on returning events before the timeout (non-infinite) is ever hit", if the Perl process is getting a denial-of-service attack through the Windows Message queue from a a different abusive process, there is nothing Perl can do about it. The PC will be 100% cpu usage anyway from the abusive process. If the messages won't be processed in win32_msgwait they will be processed anyway in assorted perl opcodes in PERL_ASYNC_CHECK()s. I was able to create a deadlock with a C debugger by doing a Perl "sleep 3;" and creating the delay with breakpoints with a C debugger. Windows running in VM or with a very badly coded driver could cause a context switch that would cause the >= 1 ms delay. I have a patch nearly complete to prevent the race condition above, but I realized a different race condition, the 49.7 day overflow, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms724408%28v=vs.85%29.aspx . The only bug the 49.7 day overflow I see creating is, if you sleep for more than 50 days, sleep() will return ~ < 1 day of sleep seconds instead of > 49 days of sleep seconds. So I have 4 choices. 1. Keep GetTickCount and put the 49.7 days of sleep actual seconds slept bug in perlwin32/BUGS AND CAVEATS section as a wont fix. Microsoft considers a likely enough scenario they test apps for the bug, see http://msdn.microsoft.com/en-us/subscriptions/aa480483.aspx and search the page for GetTickCount. 2. Replace GetTickCount with QueryPerformanceCounter http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904%28v=vs.85%29.aspx . The difficulty with this is, in what psuedo global or real global struct do I keep the frequency ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms644905%28v=vs.85%29.aspx ) in? It needs to be stored once per Perl DLL loading (non static build), or once per perl process startup (static build, no perl library dll), not queried on every ithread interp creation and stored in a my_perl member (duplicate calls to QueryPerformanceFrequency, I am probably microoptimizing here). Is there a way of storing truly process global (not interp global) data that doesn't have a const initializer or just put it in struct interp_intern and refetch it with QueryPerformanceFrequency as needed, the more efficient way is simply too difficult with perl's architecture? 3. Replace GetTickCount with GetSystemTimeAsFileTime http://msdn.microsoft.com/en-us/library/windows/desktop/ms724397%28v=vs.85%29.aspx . I dont know what GetSystemTimeAsFileTime's leap second behavior is. 4. If sleep delta > (49.7 days to seconds/2) assume we overflowed and panic/croak. This doesn't seem like a good idea. The Perl community's input is needed and appreciated. --- via perlbug: queue: perl5 status: new https://rt.perl.org:443/rt3/Ticket/Display.html?id=33096Thread Previous | Thread Next