Thread: Signals on Win32 (was RE: [HACKERS] [PATCHES] fork/exec patch)

Signals on Win32 (was RE: [HACKERS] [PATCHES] fork/exec patch)

From
"Merlin Moncure"
Date:
Zeugswetter Andreas wrote:
> How about the typical answer on Windows ? Create an invisible Window
> with an Event Handler and pass it a windows message ?

The issue at hand is not how the signal is sent, but the behavior taken
once it arrives.  Using messages bypasses the thread problem but
requires PeekMessage() to be put in various places to check if there is
a signal waiting to be acted on, which is really any easier then
SleepEx(0), although, it does bypass the threading issues.

The other main issue with messages is that processes other than the
postmaster can issue them to a backend, which has some security
implications.  Also, there is a series of rather nasty exploits based on
WM_TIMER which have only been fixed in recent versions of windows.

Merlin


Re: Signals on Win32 (was RE: [HACKERS] [PATCHES] fork/exec patch)

From
"Zeugswetter Andreas SB SD"
Date:
> > How about the typical answer on Windows ? Create an invisible Window
> > with an Event Handler and pass it a windows message ?
>
> The issue at hand is not how the signal is sent, but the behavior taken
> once it arrives.  Using messages bypasses the thread problem but
> requires PeekMessage() to be put in various places to check if there is
> a signal waiting to be acted on, which is really any easier then
> SleepEx(0), although, it does bypass the threading issues.

I think that is not correct.

            hWnd = CreateWindow ("STATIC", "", WS_POPUP, 0, 0, 0, 0,NULL,NULL,NULL,NULL);
            ShowWindow (hWnd, SW_HIDE);
        wpOrigProc = (WNDPROC) SetWindowLong(hWnd, GWL_WNDPROC, (LONG) pg_WinProc);

LRESULT APIENTRY pg_WinProc(
    HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam)
{
    MSG rMsg;

    rMsg.message = uMsg;
    rMsg.wParam = wParam;
    rMsg.lParam = lParam;

        // printf ("got message %d\n", rMsg.message);
    switch (rMsg.message)
    {
        case PG_SIGNAL_KILL:
    ......
}

Andreas

Re: Signals on Win32 (was RE: [HACKERS] [PATCHES] fork/exec patch)

From
"Merlin Moncure"
Date:
Zeugswetter Andreas wrote:
> > The issue at hand is not how the signal is sent, but the behavior
taken
> > once it arrives.  Using messages bypasses the thread problem but
> > requires PeekMessage() to be put in various places to check if there
is
> > a signal waiting to be acted on, which is really any easier then
> > SleepEx(0), although, it does bypass the threading issues.
>
> I think that is not correct.
>
>             hWnd = CreateWindow ("STATIC", "", WS_POPUP, 0, 0, 0,
[...]

The question is: is the event procedure running in the main thread or a
separate worker thread.

If it is in the main thread the signal event will not fire until the
thread sleeps or explicitly checks for waiting signal messages via
PeekMessage().  This also means working the callback into the main
backend loop.

If it is in a separate worker thread, of course the signal event will
fire immediately but execution of the main thread is not suspended,
unlike unix signals which suspend execution of the program.  This could
lead to very subtle and difficult to understand behavior unless every
signal routine can be 100% certified to run parallel to the main
execution line.  There are a couple of different ways to suspend a
thread from another thread (without true synchronization), each with
inherent problems.

Therefore, a message handler differs from normal thread synchronization
in the following ways:
1. The message pump does not necessarily have to be in a separate
thread, resulting in threadless operation.
2. The message contains both the notification and the signal itself,
removing the need to used shared memory to hold the message (as in your
example).
3. The message is not very secure.  They can come from other processes
than the postmaster.
4. When run as a service, the freedom to broadcast and receive messages
is restricted.  This restriction can be lifted, but this will be an
unpopular decision with win32 admins.  Do a search on 'service interact
desktop'.

The main reason it does not differ from a worker thread based signal
handler using synchronization objects is does get you out have having to
poll the worker thread from the main thread periodically to see if a
signal has fired.  This, of course is the major sticking point unless
signal handlers can be certified to be thread safe; not just structural
thread safety, but a more general 'do the same thing regardless if the
main thread has been suspended or not'.

Merlin



Re: Signals on Win32 (was RE: [HACKERS] [PATCHES] fork/exec patch)

From
"Magnus Hagander"
Date:
>> > How about the typical answer on Windows ? Create an
>invisible Window
>> > with an Event Handler and pass it a windows message ?
>>
>> The issue at hand is not how the signal is sent, but the
>behavior taken
>> once it arrives.  Using messages bypasses the thread problem but
>> requires PeekMessage() to be put in various places to check
>if there is
>> a signal waiting to be acted on, which is really any easier then
>> SleepEx(0), although, it does bypass the threading issues.
>
>I think that is not correct.
>
>            hWnd = CreateWindow ("STATIC", "", WS_POPUP, 0, 0,
>0, 0,NULL,NULL,NULL,NULL);
>            ShowWindow (hWnd, SW_HIDE);
>        wpOrigProc = (WNDPROC) SetWindowLong(hWnd,
>GWL_WNDPROC, (LONG) pg_WinProc);
>
>LRESULT APIENTRY pg_WinProc(
>    HWND hwnd,
>    UINT uMsg,
>    WPARAM wParam,
>    LPARAM lParam)
>{
>    MSG rMsg;
>
>    rMsg.message = uMsg;
>    rMsg.wParam = wParam;
>    rMsg.lParam = lParam;
>
>        // printf ("got message %d\n", rMsg.message);
>    switch (rMsg.message)
>    {
>        case PG_SIGNAL_KILL:
>    ......
>}


I'm quite sure he is correct. The documentation on MSDN clearly states:
[1] "An application must remove and process messages posted to the
message queues of its threads. A single-threaded application usually
uses a message loop in its WinMain function to remove and send messages
to the appropriate window procedures for processing. Applications with
multiple threads can include a message loop in each thread that creates
a window."


That message loops generally looks like:
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
    {
        if (bRet == -1)
        {
            // handle the error and possibly exit
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }


This has to be running on the thread that owns the window. Which in this
case would be the main thread of the backend, meaning it buys us
nothing.


A typical "proof" of this: The "hanging GUI" application. This is an
application that's doing other things than working it's message loop. In
that case, it can't even redraw the screen, because it can't see the
messages. The other option would be a threaded application that lock
itself out, but most of the applications that experience that problem is
not threaded. Indeed, MS recommends you create a background thread for
longer work for just this reason - to have the main thread run the
message loop.
This is slighly worked around in XP to make programs appear live even
when they're not, see [1].


//Magnus

[1]:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/w
inui/windowsuserinterface/windowing/messagesandmessagequeues/aboutmessag
esandmessagequeues.asp