Discussion:
Using SetConsoleCtrlHandler
(too old to reply)
Emmanuel Stapf [ES]
2007-06-06 01:18:06 UTC
Permalink
Hi,

I've a console single threaded application and I'm trying to catch a Ctrl+C. No
matter if I use SetConsoleCtrlHandler or a signal handler, my code to handle
this gets called in another thread. Is there a way to have the handler called
from the main thread?

In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix, using
`signal', it is called from the same thread.

Thanks for any highlight,
Manu

PS: this is shown by the code:

#include <windows.h>
#include <stdio.h>
#include <signal.h>

BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
case CTRL_C_EVENT:
printf( "Ctrl-C event\n\n" );
return TRUE;
default:
return FALSE;
}
}

void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}

void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );

printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Gary Chanson
2007-06-06 02:04:27 UTC
Permalink
What you see is what you get. ;)

How about creating an event which you can signal from your
ConsoleCtrlHandler and detect in your main thread?
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a Ctrl+C. No
matter if I use SetConsoleCtrlHandler or a signal handler, my code to handle
this gets called in another thread. Is there a way to have the handler called
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix, using
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Emmanuel Stapf [ES]
2007-06-06 02:41:20 UTC
Permalink
Post by Gary Chanson
What you see is what you get. ;)
How about creating an event which you can signal from your
ConsoleCtrlHandler and detect in your main thread?
In my case, I'm building a framework for the Eiffel language
(http://dev.eiffel.com) and I need a simple way to ensure that Ctrl+C is
translated into an exception in the current thread without having to inject too
much code that could slow down the normal execution.

So it would be nice if there was an alternative.

Regards,
Manu
Jeffrey Tan[MSFT]
2007-06-06 08:46:57 UTC
Permalink
Hi Emmanuel ,

I do not think Windows has exposed any interface for configuring this. As I
dig into the code, this behavior is by design. After the OS captured the
Ctrl+C interrupt, it will initiate a user-mode APC to schedule another
thread to call Kernel32!CtrlRoutine function, which finally calls your
registered "CtrlHandler".

Based on my knowledge, this type of asynchronous callback in Windows
normally comes in 2 forms:
1. Windows created a second thread to call the callback function.
2. Main thread in the application calls certain type of Wait*** functions
in a loop to retrieve the asynchronous notification. (This is because, the
callback notification can not interrupt the main thread without at a safe
point. ). I/O completion port uses this form

Since there is not guarantee that the console application main thread will
alway have a loop to call Wait*** functions, console handler uses the first
form.

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Skywing [MVP]
2007-06-06 15:41:05 UTC
Permalink
Are you sure that is really correct? As far as I know, the (only) behavior
is that CSRSS creates an ephemeral worker thread in the target process, via
CreateRemoteThread, which calls the registered ctrl routine list and
performs the action returned by it. I do not believe that ctrl-c really has
much, if anything to do with APCs.
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Jeffrey Tan[MSFT]
Hi Emmanuel ,
I do not think Windows has exposed any interface for configuring this. As I
dig into the code, this behavior is by design. After the OS captured the
Ctrl+C interrupt, it will initiate a user-mode APC to schedule another
thread to call Kernel32!CtrlRoutine function, which finally calls your
registered "CtrlHandler".
Based on my knowledge, this type of asynchronous callback in Windows
1. Windows created a second thread to call the callback function.
2. Main thread in the application calls certain type of Wait*** functions
in a loop to retrieve the asynchronous notification. (This is because, the
callback notification can not interrupt the main thread without at a safe
point. ). I/O completion port uses this form
Since there is not guarantee that the console application main thread will
alway have a loop to call Wait*** functions, console handler uses the first
form.
Thanks.
Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Jeffrey Tan[MSFT]
2007-06-07 02:45:57 UTC
Permalink
Hi Ken,

Thank you for sharing your thought.

Actually, if I remember correct, all the CreateThread(CreateRemoteThread)
goes into the kernel and created the kernel-mode thread structures,
finally, kernel will initiate a user-mode APC to return control to the
user-mode. Then user-mode will resolve this user APC by executing
kernel32.dll!BaseThreadStart(). Sorry, I did not check the root cause of
who called CreateThread(CreateRemoteThread).

Anyway, my key point in the reply is the second paragraph.

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Skywing [MVP]
2007-06-07 02:49:53 UTC
Permalink
Yes, that should be the same for anything that calls
CreateThread/CreateRemoteThread to spin up a user mode thread. It appeared
as if you were suggesting that the ctrl handler was invoked via an APC
queued to a pre-existing thread, which as far as I know, is not the case.
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Jeffrey Tan[MSFT]
Hi Ken,
Thank you for sharing your thought.
Actually, if I remember correct, all the CreateThread(CreateRemoteThread)
goes into the kernel and created the kernel-mode thread structures,
finally, kernel will initiate a user-mode APC to return control to the
user-mode. Then user-mode will resolve this user APC by executing
kernel32.dll!BaseThreadStart(). Sorry, I did not check the root cause of
who called CreateThread(CreateRemoteThread).
Anyway, my key point in the reply is the second paragraph.
Thanks.
Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Jeffrey Tan[MSFT]
2007-06-07 03:32:34 UTC
Permalink
Oh, yes, thank you for the clarify.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Tony Proctor
2007-06-06 09:49:25 UTC
Permalink
Windows is not very good at handling this sort of asynchronous interrupt on
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS ASTs)

The question has been asked before:
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f

I've even found myself in the same boat in trying to port a language, and
its framework, to the Windows O/S. In the end, I suspended the thread, read
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32 api
calls that had to be addressed (mentioned in that old thread)

Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a Ctrl+C. No
matter if I use SetConsoleCtrlHandler or a signal handler, my code to handle
this gets called in another thread. Is there a way to have the handler called
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix, using
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Gary Chanson
2007-06-06 13:02:59 UTC
Permalink
My solution for a similar situation was to redirect the exception to the
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a reasonable
time, so this works very nicely and is a lot cleaner they your alternative.
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt on
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Tony Proctor
I've even found myself in the same boat in trying to port a language, and
its framework, to the Windows O/S. In the end, I suspended the thread, read
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32 api
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my code to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix, using
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Tony Proctor
2007-06-07 09:38:45 UTC
Permalink
The difference there is the fact that the code must be in an alertable state
Gary. There are several possible mechanisms for an event-driven client-side
application but if it's server-side then this requirement makes the
"interrupt" less than responsive. In my case, the code was being ported from
elsewhere and wasn't event-driven (in the Windows sense) or even had a
message pump.

I admit to not having used APCs though. If the APC queue were examined when
a thread starts executing (i.e. after leaving a wait state, or being taken
off the ready-to-run queue) then it would be ideal, but I don't believe it's
implemented at that level

Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception to the
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a reasonable
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a language, and
its framework, to the Windows O/S. In the end, I suspended the thread,
read
Post by Tony Proctor
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32 api
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my code to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix, using
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Gary Chanson
2007-06-07 15:53:33 UTC
Permalink
As I said, in my case, I could make the assumption that the thread would
be in an alertable state often enough. One way of assuring that is to call
SleepEx(...,TRUE) fairly often.
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
The difference there is the fact that the code must be in an alertable state
Gary. There are several possible mechanisms for an event-driven client-side
application but if it's server-side then this requirement makes the
"interrupt" less than responsive. In my case, the code was being ported from
elsewhere and wasn't event-driven (in the Windows sense) or even had a
message pump.
I admit to not having used APCs though. If the APC queue were examined when
a thread starts executing (i.e. after leaving a wait state, or being taken
off the ready-to-run queue) then it would be ideal, but I don't believe it's
implemented at that level
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception to
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a reasonable
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a language,
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the thread,
read
Post by Tony Proctor
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my code to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Emmanuel Stapf [ES]
2007-06-07 18:25:33 UTC
Permalink
Post by Tony Proctor
I admit to not having used APCs though. If the APC queue were examined when
a thread starts executing (i.e. after leaving a wait state, or being taken
off the ready-to-run queue) then it would be ideal, but I don't believe it's
implemented at that level
I've found a Code Project sample:
http://www.codeproject.com/threads/QueueUserAPCEx_v2.asp
It mentions that one could call SuspendThread and then the undocumented
NtAlertResumeThread which would put the thread in alertable state and therefore
run the APC. But I could not make it work with the simple example I sent earlier
in my original post.

Any idea?

Thanks,
Manu
Tony Proctor
2007-06-07 09:40:08 UTC
Permalink
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work like a
UNIX developer would expect?

Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception to the
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a reasonable
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a language, and
its framework, to the Windows O/S. In the end, I suspended the thread,
read
Post by Tony Proctor
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32 api
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my code to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix, using
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Marc Sherman
2007-06-07 13:19:59 UTC
Permalink
From "Windows Internals, 4th Edition" (p. 108)

"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of POSIX
signals to POSIX processes".

Also from the same page:

"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".

That tells me they would behave like a UNIX developer would expect.

Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work like a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception to
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a reasonable
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a language,
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the thread,
read
Post by Tony Proctor
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my code to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Tony Proctor
2007-06-07 14:29:24 UTC
Permalink
Thanks Marc. That's actually very enlightening

Tony Proctor
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of POSIX
signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work
like
Post by Marc Sherman
Post by Tony Proctor
a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception to
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a reasonable
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a language,
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the thread,
read
Post by Tony Proctor
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my code to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Alexander Grigoriev
2007-06-07 15:46:14 UTC
Permalink
A BIG BIG problem with asynchronous notifications is that in a multithreaded
process there is NO reliable interrupt point, other than explicitly provided
(alertable wait). Only a single-threaded POSIX application can be
interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work like a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception to
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a reasonable
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a language,
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the thread,
read
Post by Tony Proctor
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my code to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Tony Proctor
2007-06-07 16:08:03 UTC
Permalink
I see what you're saying Alexander, but it must depend to some extent on how
closely interacting those threads are. For instance, an STA architecture
wouldn't be nearly as sensitive as a close-knit MTA one

Tony Proctor
Post by Alexander Grigoriev
A BIG BIG problem with asynchronous notifications is that in a
multithreaded
Post by Alexander Grigoriev
process there is NO reliable interrupt point, other than explicitly provided
(alertable wait). Only a single-threaded POSIX application can be
interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work
like
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception to
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a reasonable
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a language,
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the thread,
read
Post by Tony Proctor
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my code to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Skywing [MVP]
2007-06-07 16:25:02 UTC
Permalink
You may still have problems with stuff like the process heap lock.
Furthermore, I think you are still in danger even on a single threaded
system. From taking a quick look at the way the critical section
acquisition code works, it looks like if you interrupt
RtlEnterCriticalSection at the right place, you'll have the CS in an
intermediate state where it's owned but which thread owns it is not
established, such that recursive acqusition doesn't work. That means you
might be in for some trouble (race conditions resulting in a deadlock) if
you rely on recursive lock acqusition in your "signal handler" - hard to
avoid if you call anything that touches the process heap.

Specifically, consider the tail end of the successful acquire path on
RtlEnterCriticalSection:

ntdll!RtlEnterCriticalSection+0x11:
00000000`76e52685 65488b042530000000 mov rax,qword ptr gs:[30h]
00000000`76e5268e 488b4848 mov rcx,qword ptr [rax+48h]
00000000`76e52692 c7420c01000000 mov dword ptr [rdx+0Ch],1
00000000`76e52699 33c0 xor eax,eax
00000000`76e5269b 48894a10 mov qword ptr [rdx+10h],rcx
00000000`76e5269f 4883c420 add rsp,20h
00000000`76e526a3 5b pop rbx
00000000`76e526a4 c3 ret

If you suspend the thread at rip=00000000`76e52685 in this case, and then
alter context to something that tries to re-enter the same critical section
(say this is the process heap), the recursive acquire will deadlock in
RtlpWaitOnCriticalSection because the first acquire didn't get around to
marking the current thread as the owner of the critical section.

(in that case, you might see a stack like this:)

0:000> k
Child-SP RetAddr Call Site
00000000`0012fde8 00000000`76e4efc8 ntdll!NtWaitForSingleObject+0xa
00000000`0012fdf0 00000000`76e4ee8b ntdll!RtlpWaitOnCriticalSection+0xd8
00000000`0012fea0 00000000`010018ef ntdll!RtlEnterCriticalSection+0xf4
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Tony Proctor
I see what you're saying Alexander, but it must depend to some extent on how
closely interacting those threads are. For instance, an STA architecture
wouldn't be nearly as sensitive as a close-knit MTA one
Tony Proctor
Post by Alexander Grigoriev
A BIG BIG problem with asynchronous notifications is that in a
multithreaded
Post by Alexander Grigoriev
process there is NO reliable interrupt point, other than explicitly
provided
Post by Alexander Grigoriev
(alertable wait). Only a single-threaded POSIX application can be
interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work
like
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception
to
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a
reasonable
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a
language,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the
thread,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
read
Post by Tony Proctor
its context, redirected it to a point that would generate the
required
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with
win32
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to
catch
a
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my
code
to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Tony Proctor
2007-06-07 16:48:31 UTC
Permalink
True, but for an "asynchronous abort operation", which I think is what both
myself and the OP were discussing, that wouldn't be an issue Ken (as long as
it threw a s/w exception that could be handled)

Tony Proctor
Post by Skywing [MVP]
You may still have problems with stuff like the process heap lock.
Furthermore, I think you are still in danger even on a single threaded
system. From taking a quick look at the way the critical section
acquisition code works, it looks like if you interrupt
RtlEnterCriticalSection at the right place, you'll have the CS in an
intermediate state where it's owned but which thread owns it is not
established, such that recursive acqusition doesn't work. That means you
might be in for some trouble (race conditions resulting in a deadlock) if
you rely on recursive lock acqusition in your "signal handler" - hard to
avoid if you call anything that touches the process heap.
Specifically, consider the tail end of the successful acquire path on
00000000`76e52685 65488b042530000000 mov rax,qword ptr gs:[30h]
00000000`76e5268e 488b4848 mov rcx,qword ptr [rax+48h]
00000000`76e52692 c7420c01000000 mov dword ptr [rdx+0Ch],1
00000000`76e52699 33c0 xor eax,eax
00000000`76e5269b 48894a10 mov qword ptr [rdx+10h],rcx
00000000`76e5269f 4883c420 add rsp,20h
00000000`76e526a3 5b pop rbx
00000000`76e526a4 c3 ret
If you suspend the thread at rip=00000000`76e52685 in this case, and then
alter context to something that tries to re-enter the same critical section
(say this is the process heap), the recursive acquire will deadlock in
RtlpWaitOnCriticalSection because the first acquire didn't get around to
marking the current thread as the owner of the critical section.
(in that case, you might see a stack like this:)
0:000> k
Child-SP RetAddr Call Site
00000000`0012fde8 00000000`76e4efc8 ntdll!NtWaitForSingleObject+0xa
00000000`0012fdf0 00000000`76e4ee8b ntdll!RtlpWaitOnCriticalSection+0xd8
00000000`0012fea0 00000000`010018ef ntdll!RtlEnterCriticalSection+0xf4
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Tony Proctor
I see what you're saying Alexander, but it must depend to some extent on how
closely interacting those threads are. For instance, an STA architecture
wouldn't be nearly as sensitive as a close-knit MTA one
Tony Proctor
Post by Alexander Grigoriev
A BIG BIG problem with asynchronous notifications is that in a
multithreaded
Post by Alexander Grigoriev
process there is NO reliable interrupt point, other than explicitly
provided
Post by Alexander Grigoriev
(alertable wait). Only a single-threaded POSIX application can be
interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work
like
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception
to
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a
reasonable
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Skywing [MVP]
Post by Tony Proctor
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a
language,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the
thread,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
read
Post by Tony Proctor
its context, redirected it to a point that would generate the
required
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with
win32
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to
catch
a
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my
code
to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the
handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Skywing [MVP]
2007-06-07 17:07:06 UTC
Permalink
Sorry, but you're toast if you throw an SEH exception. With vectored
exception handling support, the user exception dispatcher path
(RtlDispatchException) in ntdll both acquires a critical section and can
touch the heap, in RtlpCallVectoredHandlers. If you happened to already be
in RtlEnterCriticalSection within the VEH dispatching phase of SEH exception
dispatching, you'll deadlock as soon as you raise another SEH exception.
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Tony Proctor
True, but for an "asynchronous abort operation", which I think is what both
myself and the OP were discussing, that wouldn't be an issue Ken (as long as
it threw a s/w exception that could be handled)
Tony Proctor
Post by Skywing [MVP]
You may still have problems with stuff like the process heap lock.
Furthermore, I think you are still in danger even on a single threaded
system. From taking a quick look at the way the critical section
acquisition code works, it looks like if you interrupt
RtlEnterCriticalSection at the right place, you'll have the CS in an
intermediate state where it's owned but which thread owns it is not
established, such that recursive acqusition doesn't work. That means you
might be in for some trouble (race conditions resulting in a deadlock) if
you rely on recursive lock acqusition in your "signal handler" - hard to
avoid if you call anything that touches the process heap.
Specifically, consider the tail end of the successful acquire path on
00000000`76e52685 65488b042530000000 mov rax,qword ptr gs:[30h]
00000000`76e5268e 488b4848 mov rcx,qword ptr [rax+48h]
00000000`76e52692 c7420c01000000 mov dword ptr [rdx+0Ch],1
00000000`76e52699 33c0 xor eax,eax
00000000`76e5269b 48894a10 mov qword ptr [rdx+10h],rcx
00000000`76e5269f 4883c420 add rsp,20h
00000000`76e526a3 5b pop rbx
00000000`76e526a4 c3 ret
If you suspend the thread at rip=00000000`76e52685 in this case, and then
alter context to something that tries to re-enter the same critical
section
Post by Skywing [MVP]
(say this is the process heap), the recursive acquire will deadlock in
RtlpWaitOnCriticalSection because the first acquire didn't get around to
marking the current thread as the owner of the critical section.
(in that case, you might see a stack like this:)
0:000> k
Child-SP RetAddr Call Site
00000000`0012fde8 00000000`76e4efc8 ntdll!NtWaitForSingleObject+0xa
00000000`0012fdf0 00000000`76e4ee8b ntdll!RtlpWaitOnCriticalSection+0xd8
00000000`0012fea0 00000000`010018ef ntdll!RtlEnterCriticalSection+0xf4
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Tony Proctor
I see what you're saying Alexander, but it must depend to some extent on how
closely interacting those threads are. For instance, an STA
architecture
wouldn't be nearly as sensitive as a close-knit MTA one
Tony Proctor
Post by Alexander Grigoriev
A BIG BIG problem with asynchronous notifications is that in a
multithreaded
Post by Alexander Grigoriev
process there is NO reliable interrupt point, other than explicitly
provided
Post by Alexander Grigoriev
(alertable wait). Only a single-threaded POSIX application can be
interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work
like
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the
exception
Post by Skywing [MVP]
Post by Tony Proctor
to
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be
reasonably
Post by Skywing [MVP]
Post by Tony Proctor
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
certain that the task will enter an alertable state within a
reasonable
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
in
Post by Skywing [MVP]
Post by Tony Proctor
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous
interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even
VMS
Post by Skywing [MVP]
Post by Tony Proctor
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Skywing [MVP]
Post by Tony Proctor
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a
language,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the
thread,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
read
Post by Tony Proctor
its context, redirected it to a point that would generate the
required
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with
win32
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to
catch
a
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my
code
to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the
handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On
Unix,
Post by Skywing [MVP]
Post by Tony Proctor
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Marc Sherman
2007-06-07 17:10:49 UTC
Permalink
From my Solaris days, IIRC, you're supposed to do the bare minimum in a
signal handler. Kind of like win32's DllMain restrictions. Sticking to the
"bare minimum" principal should work even in multithreaded POSIX apps, I
believe.
Post by Skywing [MVP]
You may still have problems with stuff like the process heap lock.
Furthermore, I think you are still in danger even on a single threaded
system. From taking a quick look at the way the critical section
acquisition code works, it looks like if you interrupt
RtlEnterCriticalSection at the right place, you'll have the CS in an
intermediate state where it's owned but which thread owns it is not
established, such that recursive acqusition doesn't work. That means you
might be in for some trouble (race conditions resulting in a deadlock) if
you rely on recursive lock acqusition in your "signal handler" - hard to
avoid if you call anything that touches the process heap.
Specifically, consider the tail end of the successful acquire path on
00000000`76e52685 65488b042530000000 mov rax,qword ptr gs:[30h]
00000000`76e5268e 488b4848 mov rcx,qword ptr [rax+48h]
00000000`76e52692 c7420c01000000 mov dword ptr [rdx+0Ch],1
00000000`76e52699 33c0 xor eax,eax
00000000`76e5269b 48894a10 mov qword ptr [rdx+10h],rcx
00000000`76e5269f 4883c420 add rsp,20h
00000000`76e526a3 5b pop rbx
00000000`76e526a4 c3 ret
If you suspend the thread at rip=00000000`76e52685 in this case, and then
alter context to something that tries to re-enter the same critical
section (say this is the process heap), the recursive acquire will
deadlock in RtlpWaitOnCriticalSection because the first acquire didn't get
around to marking the current thread as the owner of the critical section.
(in that case, you might see a stack like this:)
0:000> k
Child-SP RetAddr Call Site
00000000`0012fde8 00000000`76e4efc8 ntdll!NtWaitForSingleObject+0xa
00000000`0012fdf0 00000000`76e4ee8b ntdll!RtlpWaitOnCriticalSection+0xd8
00000000`0012fea0 00000000`010018ef ntdll!RtlEnterCriticalSection+0xf4
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Tony Proctor
I see what you're saying Alexander, but it must depend to some extent on how
closely interacting those threads are. For instance, an STA architecture
wouldn't be nearly as sensitive as a close-knit MTA one
Tony Proctor
Post by Alexander Grigoriev
A BIG BIG problem with asynchronous notifications is that in a
multithreaded
Post by Alexander Grigoriev
process there is NO reliable interrupt point, other than explicitly
provided
Post by Alexander Grigoriev
(alertable wait). Only a single-threaded POSIX application can be
interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work
like
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception
to
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a
reasonable
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a
language,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the
thread,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
read
Post by Tony Proctor
its context, redirected it to a point that would generate the
required
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with
win32
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to
catch
a
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my
code
to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Skywing [MVP]
2007-06-07 17:27:06 UTC
Permalink
Yes, although with the proposed implementation, the restrictions are
extremely severe:

- No critical sections can be acquired as they do not support interruption
in the acquisition process and will break recursive acquire support

Because it is virtually impossible to do much of anything in Win32 without
doing one of those (for instance, SEH dispatching acquires a critical
section, any dll that hits the loader lock acquires a critical section, any
dll that allocates heap memory acquires a critical section, ... how many
APIs can you think of that do useful work and are guaranteed to never do one
of those tasks), you would pretty much be limited to something like setting
a flag in a global variable and resuming execution.

Since you cannot predict what critical sections an interrupted code fragment
might have acquired or be attempting to acquire, you must assume that ALL
critical sections in the process are off limits. There are of course other
problems besides critical sections, but they are probably one of the first
big difficult-to-cope-with problems that may crop up if you are not
extraordinarily careful and conservative in what you do.
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Marc Sherman
From my Solaris days, IIRC, you're supposed to do the bare minimum in a
signal handler. Kind of like win32's DllMain restrictions. Sticking to the
"bare minimum" principal should work even in multithreaded POSIX apps, I
believe.
Post by Skywing [MVP]
You may still have problems with stuff like the process heap lock.
Furthermore, I think you are still in danger even on a single threaded
system. From taking a quick look at the way the critical section
acquisition code works, it looks like if you interrupt
RtlEnterCriticalSection at the right place, you'll have the CS in an
intermediate state where it's owned but which thread owns it is not
established, such that recursive acqusition doesn't work. That means you
might be in for some trouble (race conditions resulting in a deadlock) if
you rely on recursive lock acqusition in your "signal handler" - hard to
avoid if you call anything that touches the process heap.
Specifically, consider the tail end of the successful acquire path on
00000000`76e52685 65488b042530000000 mov rax,qword ptr gs:[30h]
00000000`76e5268e 488b4848 mov rcx,qword ptr [rax+48h]
00000000`76e52692 c7420c01000000 mov dword ptr [rdx+0Ch],1
00000000`76e52699 33c0 xor eax,eax
00000000`76e5269b 48894a10 mov qword ptr [rdx+10h],rcx
00000000`76e5269f 4883c420 add rsp,20h
00000000`76e526a3 5b pop rbx
00000000`76e526a4 c3 ret
If you suspend the thread at rip=00000000`76e52685 in this case, and then
alter context to something that tries to re-enter the same critical
section (say this is the process heap), the recursive acquire will
deadlock in RtlpWaitOnCriticalSection because the first acquire didn't
get around to marking the current thread as the owner of the critical
section.
(in that case, you might see a stack like this:)
0:000> k
Child-SP RetAddr Call Site
00000000`0012fde8 00000000`76e4efc8 ntdll!NtWaitForSingleObject+0xa
00000000`0012fdf0 00000000`76e4ee8b ntdll!RtlpWaitOnCriticalSection+0xd8
00000000`0012fea0 00000000`010018ef ntdll!RtlEnterCriticalSection+0xf4
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Tony Proctor
I see what you're saying Alexander, but it must depend to some extent on how
closely interacting those threads are. For instance, an STA architecture
wouldn't be nearly as sensitive as a close-knit MTA one
Tony Proctor
Post by Alexander Grigoriev
A BIG BIG problem with asynchronous notifications is that in a
multithreaded
Post by Alexander Grigoriev
process there is NO reliable interrupt point, other than explicitly
provided
Post by Alexander Grigoriev
(alertable wait). Only a single-threaded POSIX application can be
interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work
like
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception
to
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a
reasonable
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a
language,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the
thread,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
read
Post by Tony Proctor
its context, redirected it to a point that would generate the
required
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with
win32
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to
catch
a
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my
code
to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the
handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Marc Sherman
2007-06-07 18:12:51 UTC
Permalink
"... you would pretty much be limited to something like setting
a flag in a global variable and resuming execution."

Agreed. In another post in this thread, I mentioned either setting a global
or an event as the most that should be done. I think I'll pare that down to
just setting a global because who knows what setting an event (or signalling
a posix conditional variable) does under the covers.
Post by Skywing [MVP]
Yes, although with the proposed implementation, the restrictions are
- No critical sections can be acquired as they do not support interruption
in the acquisition process and will break recursive acquire support
Because it is virtually impossible to do much of anything in Win32 without
doing one of those (for instance, SEH dispatching acquires a critical
section, any dll that hits the loader lock acquires a critical section,
any dll that allocates heap memory acquires a critical section, ... how
many APIs can you think of that do useful work and are guaranteed to never
do one of those tasks), you would pretty much be limited to something like
setting a flag in a global variable and resuming execution.
Since you cannot predict what critical sections an interrupted code
fragment might have acquired or be attempting to acquire, you must assume
that ALL critical sections in the process are off limits. There are of
course other problems besides critical sections, but they are probably one
of the first big difficult-to-cope-with problems that may crop up if you
are not extraordinarily careful and conservative in what you do.
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Marc Sherman
From my Solaris days, IIRC, you're supposed to do the bare minimum in a
signal handler. Kind of like win32's DllMain restrictions. Sticking to
the "bare minimum" principal should work even in multithreaded POSIX
apps, I believe.
Post by Skywing [MVP]
You may still have problems with stuff like the process heap lock.
Furthermore, I think you are still in danger even on a single threaded
system. From taking a quick look at the way the critical section
acquisition code works, it looks like if you interrupt
RtlEnterCriticalSection at the right place, you'll have the CS in an
intermediate state where it's owned but which thread owns it is not
established, such that recursive acqusition doesn't work. That means
you might be in for some trouble (race conditions resulting in a
deadlock) if you rely on recursive lock acqusition in your "signal
handler" - hard to avoid if you call anything that touches the process
heap.
Specifically, consider the tail end of the successful acquire path on
00000000`76e52685 65488b042530000000 mov rax,qword ptr gs:[30h]
00000000`76e5268e 488b4848 mov rcx,qword ptr [rax+48h]
00000000`76e52692 c7420c01000000 mov dword ptr [rdx+0Ch],1
00000000`76e52699 33c0 xor eax,eax
00000000`76e5269b 48894a10 mov qword ptr [rdx+10h],rcx
00000000`76e5269f 4883c420 add rsp,20h
00000000`76e526a3 5b pop rbx
00000000`76e526a4 c3 ret
If you suspend the thread at rip=00000000`76e52685 in this case, and
then alter context to something that tries to re-enter the same critical
section (say this is the process heap), the recursive acquire will
deadlock in RtlpWaitOnCriticalSection because the first acquire didn't
get around to marking the current thread as the owner of the critical
section.
(in that case, you might see a stack like this:)
0:000> k
Child-SP RetAddr Call Site
00000000`0012fde8 00000000`76e4efc8 ntdll!NtWaitForSingleObject+0xa
00000000`0012fdf0 00000000`76e4ee8b ntdll!RtlpWaitOnCriticalSection+0xd8
00000000`0012fea0 00000000`010018ef ntdll!RtlEnterCriticalSection+0xf4
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Tony Proctor
I see what you're saying Alexander, but it must depend to some extent on how
closely interacting those threads are. For instance, an STA
architecture
wouldn't be nearly as sensitive as a close-knit MTA one
Tony Proctor
Post by Alexander Grigoriev
A BIG BIG problem with asynchronous notifications is that in a
multithreaded
Post by Alexander Grigoriev
process there is NO reliable interrupt point, other than explicitly
provided
Post by Alexander Grigoriev
(alertable wait). Only a single-threaded POSIX application can be
interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work
like
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception
to
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a
reasonable
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous
interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a
language,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the
thread,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
read
Post by Tony Proctor
its context, redirected it to a point that would generate the
required
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with
win32
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to
catch
a
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my
code
to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the
handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Alexander Grigoriev
2007-06-08 03:24:07 UTC
Permalink
Global variable and event can easily be done just from a separate thread
dedicated to handle signals. These are not tied to a thread.

The really interesting stuff begins when you need to do something _on
behalf_ of the interrupted thread. Then you can screw things very easily.
And there may not even be a reliable way to do what you want, such as
longjmp.
Post by Marc Sherman
"... you would pretty much be limited to something like setting
a flag in a global variable and resuming execution."
Agreed. In another post in this thread, I mentioned either setting a
global or an event as the most that should be done. I think I'll pare that
down to just setting a global because who knows what setting an event (or
signalling a posix conditional variable) does under the covers.
Post by Skywing [MVP]
Yes, although with the proposed implementation, the restrictions are
- No critical sections can be acquired as they do not support
interruption in the acquisition process and will break recursive acquire
support
Because it is virtually impossible to do much of anything in Win32
without doing one of those (for instance, SEH dispatching acquires a
critical section, any dll that hits the loader lock acquires a critical
section, any dll that allocates heap memory acquires a critical section,
... how many APIs can you think of that do useful work and are guaranteed
to never do one of those tasks), you would pretty much be limited to
something like setting a flag in a global variable and resuming
execution.
Since you cannot predict what critical sections an interrupted code
fragment might have acquired or be attempting to acquire, you must assume
that ALL critical sections in the process are off limits. There are of
course other problems besides critical sections, but they are probably
one of the first big difficult-to-cope-with problems that may crop up if
you are not extraordinarily careful and conservative in what you do.
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Marc Sherman
From my Solaris days, IIRC, you're supposed to do the bare minimum in a
signal handler. Kind of like win32's DllMain restrictions. Sticking to
the "bare minimum" principal should work even in multithreaded POSIX
apps, I believe.
Post by Skywing [MVP]
You may still have problems with stuff like the process heap lock.
Furthermore, I think you are still in danger even on a single threaded
system. From taking a quick look at the way the critical section
acquisition code works, it looks like if you interrupt
RtlEnterCriticalSection at the right place, you'll have the CS in an
intermediate state where it's owned but which thread owns it is not
established, such that recursive acqusition doesn't work. That means
you might be in for some trouble (race conditions resulting in a
deadlock) if you rely on recursive lock acqusition in your "signal
handler" - hard to avoid if you call anything that touches the process
heap.
Specifically, consider the tail end of the successful acquire path on
00000000`76e52685 65488b042530000000 mov rax,qword ptr gs:[30h]
00000000`76e5268e 488b4848 mov rcx,qword ptr [rax+48h]
00000000`76e52692 c7420c01000000 mov dword ptr [rdx+0Ch],1
00000000`76e52699 33c0 xor eax,eax
00000000`76e5269b 48894a10 mov qword ptr [rdx+10h],rcx
00000000`76e5269f 4883c420 add rsp,20h
00000000`76e526a3 5b pop rbx
00000000`76e526a4 c3 ret
If you suspend the thread at rip=00000000`76e52685 in this case, and
then alter context to something that tries to re-enter the same
critical section (say this is the process heap), the recursive acquire
will deadlock in RtlpWaitOnCriticalSection because the first acquire
didn't get around to marking the current thread as the owner of the
critical section.
(in that case, you might see a stack like this:)
0:000> k
Child-SP RetAddr Call Site
00000000`0012fde8 00000000`76e4efc8 ntdll!NtWaitForSingleObject+0xa
00000000`0012fdf0 00000000`76e4ee8b
ntdll!RtlpWaitOnCriticalSection+0xd8
00000000`0012fea0 00000000`010018ef ntdll!RtlEnterCriticalSection+0xf4
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Tony Proctor
I see what you're saying Alexander, but it must depend to some extent on how
closely interacting those threads are. For instance, an STA architecture
wouldn't be nearly as sensitive as a close-knit MTA one
Tony Proctor
Post by Alexander Grigoriev
A BIG BIG problem with asynchronous notifications is that in a
multithreaded
Post by Alexander Grigoriev
process there is NO reliable interrupt point, other than explicitly
provided
Post by Alexander Grigoriev
(alertable wait). Only a single-threaded POSIX application can be
interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work
like
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception
to
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a
reasonable
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous
interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a
language,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the
thread,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
read
Post by Tony Proctor
its context, redirected it to a point that would generate the
required
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
exception, and then released it. Surprisingly, it worked OK in
practice
(although not on Alpha AXP H/W) but there were a few issues with
win32
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to
catch
a
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my
code
to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the
handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler,
TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Alexander Grigoriev
2007-06-08 03:20:13 UTC
Permalink
Any multithreaded process uses locks behind your back, when you call heap
allocation or stdio functions. You cannot be sure when the locks are not
held. single-thread process doesn't have to hold any locks, and even if it
does, the locks are reentrant, so dropping one is not dangerous.
Post by Tony Proctor
I see what you're saying Alexander, but it must depend to some extent on how
closely interacting those threads are. For instance, an STA architecture
wouldn't be nearly as sensitive as a close-knit MTA one
Tony Proctor
Post by Alexander Grigoriev
A BIG BIG problem with asynchronous notifications is that in a
multithreaded
Post by Alexander Grigoriev
process there is NO reliable interrupt point, other than explicitly
provided
Post by Alexander Grigoriev
(alertable wait). Only a single-threaded POSIX application can be
interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work
like
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception
to
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a
reasonable
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a
language,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the
thread,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
read
Post by Tony Proctor
its context, redirected it to a point that would generate the
required
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with
win32
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to
catch
a
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my
code
to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Skywing [MVP]
2007-06-08 13:57:38 UTC
Permalink
Yes, but you can break the re-entrant features of some locks (e.g. critical
sections) if you suspend and interrupt the acquire process at the right
time.
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Alexander Grigoriev
Any multithreaded process uses locks behind your back, when you call heap
allocation or stdio functions. You cannot be sure when the locks are not
held. single-thread process doesn't have to hold any locks, and even if it
does, the locks are reentrant, so dropping one is not dangerous.
Post by Tony Proctor
I see what you're saying Alexander, but it must depend to some extent on how
closely interacting those threads are. For instance, an STA architecture
wouldn't be nearly as sensitive as a close-knit MTA one
Tony Proctor
Post by Alexander Grigoriev
A BIG BIG problem with asynchronous notifications is that in a
multithreaded
Post by Alexander Grigoriev
process there is NO reliable interrupt point, other than explicitly
provided
Post by Alexander Grigoriev
(alertable wait). Only a single-threaded POSIX application can be
interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work
like
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception
to
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a
reasonable
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a
language,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the
thread,
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
read
Post by Tony Proctor
its context, redirected it to a point that would generate the
required
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with
win32
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to
catch
a
Post by Alexander Grigoriev
Post by Marc Sherman
Post by Tony Proctor
Post by Gary Chanson
Post by Tony Proctor
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my
code
to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Marc Sherman
2007-06-07 16:08:20 UTC
Permalink
Assuming the signal handler does the minimum (ie. set a global, set an
event) and never tries to acquire a lock (explicitly or implicitly), would
there still be a problem in a multithreaded POSIX app?
Post by Alexander Grigoriev
A BIG BIG problem with asynchronous notifications is that in a
multithreaded process there is NO reliable interrupt point, other than
explicitly provided (alertable wait). Only a single-threaded POSIX
application can be interrupted at a random instruction without ill effects.
Post by Marc Sherman
From "Windows Internals, 4th Edition" (p. 108)
"The POSIX subsystem uses kernel-mode APCs to emulate the delivery of
POSIX signals to POSIX processes".
"Kernel mode APCs interrupt a thread and execute a procedure without the
thread's intervention or consent".
That tells me they would behave like a UNIX developer would expect.
Marc
Post by Tony Proctor
...actually, I don't suppose anyone knows how things like SIGINT are
implemented in the POSIX sub-system under Windows. Do they even work like a
UNIX developer would expect?
Tony Proctor
Post by Gary Chanson
My solution for a similar situation was to redirect the exception to
the
Post by Gary Chanson
appropriate thread using a User APC. In my case, I can be reasonably
certain that the task will enter an alertable state within a reasonable
time, so this works very nicely and is a lot cleaner they your
alternative.
Post by Gary Chanson
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt
on
Post by Tony Proctor
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS
ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Gary Chanson
Post by Tony Proctor
I've even found myself in the same boat in trying to port a language,
and
Post by Gary Chanson
Post by Tony Proctor
its framework, to the Windows O/S. In the end, I suspended the thread,
read
Post by Tony Proctor
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32
api
Post by Gary Chanson
Post by Tony Proctor
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my code to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix,
using
Post by Gary Chanson
Post by Tony Proctor
Post by Emmanuel Stapf [ES]
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Skywing [MVP]
2007-06-06 15:44:31 UTC
Permalink
This seems a bit fishy and not-recommendable to me... Get/SetThreadContext
when you are in a system call will not have the expected result, some of the
volatile registers (which might be parameter registers for fastcall, or even
more problematic on x64) will be overwritten on return from the system call.
And setting the context will not take effect until the system call returns
anyway. There is also the problem that you don't have a way to wake a
thread that was sleeping.

Furthermore, if you happen to catch a thread "at a bad time", such as when
it owns an important lock (or even worse, is in the middle of acquiring an
important lock, like the critical section for the process heap, such that
you break recursive acquisition of it), you're likely to break the process
(deadlock).
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt on
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
I've even found myself in the same boat in trying to port a language, and
its framework, to the Windows O/S. In the end, I suspended the thread, read
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32 api
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my code to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix, using
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Tony Proctor
2007-06-06 16:32:35 UTC
Permalink
Obviously it checked for a thread currently in a wait state Ken, and - as
the old thread says - it relied on correct exception handling elsewhere to
release any locks/resources held at the point of interruption. I agree
though that it's not really recommenable in the general case. The only
reason it worked for me was probably because the code was C (not C++ so less
resource ownership issues), and I ended up wrapping every system call as
indicated, just in case (which was easy because all the low-level runtime
support had been abstracted for portability anyway)

Tony Proctor
Post by Skywing [MVP]
This seems a bit fishy and not-recommendable to me...
Get/SetThreadContext
Post by Skywing [MVP]
when you are in a system call will not have the expected result, some of the
volatile registers (which might be parameter registers for fastcall, or even
more problematic on x64) will be overwritten on return from the system call.
And setting the context will not take effect until the system call returns
anyway. There is also the problem that you don't have a way to wake a
thread that was sleeping.
Furthermore, if you happen to catch a thread "at a bad time", such as when
it owns an important lock (or even worse, is in the middle of acquiring an
important lock, like the critical section for the process heap, such that
you break recursive acquisition of it), you're likely to break the process
(deadlock).
--
Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
Post by Tony Proctor
Windows is not very good at handling this sort of asynchronous interrupt on
a single thread Emmanuel (i.e. similar to UNIX signals, or even VMS ASTs)
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106f
Post by Skywing [MVP]
Post by Tony Proctor
I've even found myself in the same boat in trying to port a language, and
its framework, to the Windows O/S. In the end, I suspended the thread, read
its context, redirected it to a point that would generate the required
exception, and then released it. Surprisingly, it worked OK in practice
(although not on Alpha AXP H/W) but there were a few issues with win32 api
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
Post by Emmanuel Stapf [ES]
Hi,
I've a console single threaded application and I'm trying to catch a
Ctrl+C. No
Post by Emmanuel Stapf [ES]
matter if I use SetConsoleCtrlHandler or a signal handler, my code to
handle
Post by Emmanuel Stapf [ES]
this gets called in another thread. Is there a way to have the handler
called
Post by Emmanuel Stapf [ES]
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On Unix, using
`signal', it is called from the same thread.
Thanks for any highlight,
Manu
#include <windows.h>
#include <stdio.h>
#include <signal.h>
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType ) {
printf( "Ctrl-C event\n\n" );
return TRUE;
return FALSE;
}
}
void handler (int sig) {
printf ("From Signal\n");
signal (SIGINT, handler);
}
void main( void )
{
signal (SIGINT, handler);
//SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
printf("Use Ctrl+C to see what is going on.\n" );
while( 1 ){ }
}
Emmanuel Stapf [ES]
2007-06-07 04:32:26 UTC
Permalink
Thanks for the feedback and the link to the other discussion thread, it was very
helpful. We will see if we end up implementing this solution or something else.

Regards,
Manu
Continue reading on narkive:
Loading...