Re: Using SetConsoleCtrlHandler
- From: "Alexander Grigoriev" <alegr@xxxxxxxxxxxxx>
- Date: Thu, 7 Jun 2007 20:24:07 -0700
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.
"Marc Sherman" <masherman1970@xxxxxxxxx> wrote in message
news:uOHLb%23SqHHA.5032@xxxxxxxxxxxxxxxxxxxxxxx
"... 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.
"Skywing [MVP]" <skywing_NO_SPAM_@xxxxxxxxxxxxxxxxxxx> wrote in message
news:eirOTkSqHHA.4280@xxxxxxxxxxxxxxxxxxxxxxx
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
"Marc Sherman" <masherman1970@xxxxxxxxx> wrote in message
news:%23TYSfbSqHHA.3484@xxxxxxxxxxxxxxxxxxxxxxx
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.
"Skywing [MVP]" <skywing_NO_SPAM_@xxxxxxxxxxxxxxxxxxx> wrote in message
news:e%23ZmnBSqHHA.3296@xxxxxxxxxxxxxxxxxxxxxxx
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
"Tony Proctor" <tony_proctor@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx> wrote in
message news:O7u2I4RqHHA.4536@xxxxxxxxxxxxxxxxxxxxxxx
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
"Alexander Grigoriev" <alegr@xxxxxxxxxxxxx> wrote in message
news:u0k46rRqHHA.1208@xxxxxxxxxxxxxxxxxxxxxxx
A BIG BIG problem with asynchronous notifications is that in amultithreaded
process there is NO reliable interrupt point, other than explicitlyprovided
(alertable wait). Only a single-threaded POSIX application can belike
interrupted at a random instruction without ill effects.
"Marc Sherman" <masherman1970@xxxxxxxxx> wrote in message
news:O1XaNaQqHHA.4520@xxxxxxxxxxxxxxxxxxxxxxx
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
"Tony Proctor" <tony_proctor@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx> wrote
in
message news:eEO3XfOqHHA.3296@xxxxxxxxxxxxxxxxxxxxxxx
...actually, I don't suppose anyone knows how things like SIGINT
are
implemented in the POSIX sub-system under Windows. Do they even
work
toa
UNIX developer would expect?
Tony Proctor
"Gary Chanson" <gchanson@xxxxxxxxxxxxxxxx> wrote in message
news:O$s$jsDqHHA.4132@xxxxxxxxxxxxxxxxxxxxxxx
My solution for a similar situation was to redirect the
exception
reasonablethe
appropriate thread using a User APC. In my case, I can be
reasonably
certain that the task will enter an alertable state within a
http://groups.google.ie/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/608ad10204f76515/1e175f06dca6106f?hl=en#1e175f06dca6106ftime, so this works very nicely and is a lot cleaner they youralternative.
message
--
- Gary Chanson (Windows SDK MVP)
- Abolish Public Schools
"Tony Proctor" <tony_proctor@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx> wrote
in
news:eFnX5$BqHHA.1148@xxxxxxxxxxxxxxxxxxxxxxxASTs)
Windows is not very good at handling this sort of asynchronouson
interrupt
a single thread Emmanuel (i.e. similar to UNIX signals, or even
VMS
The question has been asked before:
language,
I've even found myself in the same boat in trying to port a
thread,and
its framework, to the Windows O/S. In the end, I suspended the
requiredread
its context, redirected it to a point that would generate the
win32exception, and then released it. Surprisingly, it worked OK in
practice
(although not on Alpha AXP H/W) but there were a few issues
with
aapi
calls that had to be addressed (mentioned in that old thread)
Tony Proctor
"Emmanuel Stapf [ES]" <manus@xxxxxxxxxxxxxxxxx> wrote in
message
news:uQhAUi9pHHA.1144@xxxxxxxxxxxxxxxxxxxxxxx
Hi,
I've a console single threaded application and I'm trying to
catch
usingCtrl+C. No
matter if I use SetConsoleCtrlHandler or a signal handler, myhandle
code
to
this gets called in another thread. Is there a way to havecalled
the
handler
from the main thread?
In the code below, simply comment the call to `signal' or to
`SetConsoleCtrlHandler' to observe the similar behavior. On
Unix,
`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 ){ }
}
.
- References:
- Using SetConsoleCtrlHandler
- From: Emmanuel Stapf [ES]
- Re: Using SetConsoleCtrlHandler
- From: Tony Proctor
- Re: Using SetConsoleCtrlHandler
- From: Gary Chanson
- Re: Using SetConsoleCtrlHandler
- From: Tony Proctor
- Re: Using SetConsoleCtrlHandler
- From: Marc Sherman
- Re: Using SetConsoleCtrlHandler
- From: Alexander Grigoriev
- Re: Using SetConsoleCtrlHandler
- From: Tony Proctor
- Re: Using SetConsoleCtrlHandler
- From: Skywing [MVP]
- Re: Using SetConsoleCtrlHandler
- From: Marc Sherman
- Re: Using SetConsoleCtrlHandler
- From: Skywing [MVP]
- Re: Using SetConsoleCtrlHandler
- From: Marc Sherman
- Using SetConsoleCtrlHandler
- Prev by Date: Re: Using SetConsoleCtrlHandler
- Next by Date: Re: Common place to write application data
- Previous by thread: Re: Using SetConsoleCtrlHandler
- Next by thread: Re: Using SetConsoleCtrlHandler
- Index(es):
Relevant Pages
|