https://bugs.winehq.org/show_bug.cgi?id=37669
--- Comment #16 from Dmitry Timoshkov dmitry@baikal.ru --- Hi Sebastian,
after quite a bit of testing I prefer your approach. Unfortunately there is one thing that doesn't work with your patch. It's the asynchronous recv(). Actually that's not your fault, that's a general limitation of async callbacks implementation in Wine.
wineserver sends a SIGUSR1 signal to a thread in order to execute an apc (server/thread.c,queue_apc()). USR1 signal handler (dlls/ntdll/signal_i386.c, usr1_handler()) shares the same code for suspending a thread with executing a scheduled apc, and it's executed on the signal stack. This means that during apc execution exceptions can't be handled, and in case of an exception the thread will be killed. An apc that is being executed calls dlls/ws2_32/socket.c, WS2_async_recv(), which in turn calls WS2_recv() and it triggers a write watch exception either by calling IsBadWritePtr() in your patch or memcpy() in mine hack => thread dies.
In order to solve this either apc callback should avoid generating exceptions, or it should be executed on win32 stack instead, perhaps wine_call_on_stack is the way to achieve that. Avoiding generating exceptions seems unfeasible to me, VirtualQuery() doesn't provide a way to detect write watchable memory, and I don't see another way to determine why recvmsg has returned EFAULT.
I'd appreciate your thoughts on this problem.