Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Socket IO on Windows can crash the VM with an access violation due to a race condition on memory freeing in aioWin.c. The sequence of events that can lead to the crash is: allHandles is malloc'd in aioPoll() and passed to sliceWaitForMultipleObjects(). sliceWaitForMultipleObjects() stores a pointer to allHandles in sliceData->handles. waitHandlesThreadFunction() is then called from one or more threads and copies the data from allHandles. aioPoll() then waits for an event using WaitForMultipleObjectsEx(). Once WaitForMultipleObjectsEx() returns it checks the results and frees allHandles. However this assumes that every thread gets a chance to run prior to WaitForMultipleObjectsEx() returning. But WaitForMultipleObjectsEx() will return either after a timeout or after the first thread indicates an event - since WaitForMultipleObjectsEx() is called with bWaitAll = FALSE. On a machine with only a couple of cores and a large number of sockets open allHandles can be freed prior to all threads getting enough CPU time, causing an access violation. The solution is to allocate a buffer per thread and copy the relevant portion of allHandles in to it prior to spawning the thread. As not all threads get a chance to complete prior to WaitForMultipleObjectsEx() returning, it also means that socket IO may not be recognised, and the socket not read (or written). Polling all sockets even on timeout ensures that all IO is recognised. The time for checkEventsInHandles() is less than 1mS, so the overhead is minimal, with basically no work being done if no handles are registered for asynchronous IO. Fixes: pharo-project#495
- Loading branch information