Send signals in windows

Sending an arbitrary Signal in Windows?

Linux supports sending an arbitrary Posix-Signal such as SIGINT or SIGTERM to a process using the kill -Command. While SIGINT and SIGTERM are just boring old ways to end a process in a friendly or not-so-friendly kind of way, SIGQUIT is meant to trigger a core dump. This can be used to trigger a running Java VM to print out a thread dump, including the stacktraces of all running threads — neat! After printing the debugging info, the Java VM will continue doing whatever it was doing before; in fact the thread dump just happens in another spawned thread of maximum priority. (You can try this out yourself by using kill -3 .)

Note that you can also register your own signal handlers using the (unsupported!) Signal and SignalHandler classes in the sun.misc -package, so you can have all kinds of fun with it.

However, I have yet to find a way to send a signal to a Windows process. Signals are created by certain user inputs: Ctrl-C triggers a SIGINT on both platforms, for instance. But there does not seem to be any utility to manually send a signal to a running, but non-interactive process on Windows. The obvious solution is to use the Cygwin kill executable, but while it can end Windows processes using the appropriate Windows API, I could not send a SIGBREAK (the Windows equivalent to SIGQUIT ) with it; in fact I think the only signal it is able to send to Windows processes is SIGTERM .

So, to make a long story short and to repeat the headline: How to I send an arbitrary signal to a process in Windows?

Signal handling on Windows

I have a standalone PHP script, and I would handle a signal sent from Windows OS to do a graceful shutdown when a «kill signal» is issued.

How can I do that on Windows?

2 Answers 2

Update March 2020: As of PHP 7.4, there is sapi_windows_set_ctrl_handler() and sapi_windows_generate_ctrl_event. This lets your script handle Ctrl+C and Ctrl+Break keypresses as well as generate them for other processes in the same process group. proc_open() has also added the create_process_group option to allow the child process to handle CTRL events. This is the best you can do on Windows as far as signal handling goes. Note that these functions are only available to the PHP CLI SAPI (i.e. php.exe) and they only function when the process is attached to a console, which somewhat limits their usefulness.

While the only other answer here is succinct and accurate, it lacks detail on why there isn’t signal support on Windows.

First off, signals are a rather limited and outdated way of communicating with a process. There are many more richer ways to inform a process that it needs to drop what it is doing and do something else. Even on POSIX platforms, signal handlers are intended to be VERY lightweight — code in signal handlers has to be ready/capable of handling multiple signals arriving at the same time.

PHP allows for signal handlers via pcntl_signal() with a significant number of caveats. Before they can be used, the code has to adjust the number of «ticks» that pass before PHP will pass a signal that arrived onto a handler. A tick is the number of instructions that Zend (the core of PHP) will execute before checking the signal handler status and running the necessary callbacks. It’s basically a busy loop within the main execution loop. As such, adjusting ticks will dramatically slow down the process if the per-tick recommendation of 1 is followed. The comments on the function suggest a tick value of 100 is sufficient on most systems. The easiest way to understand how the handler works is that there is an actual signal handler behind the scenes that collects signal information, which PHP occasionally queries to see if the handler was called, which signal was sent, etc. — if so, then the information is passed along to a callback in userland (i.e your code). It’s not real signal handling and never will be due to the dangers and difficulties that real signal handling presents.

Читайте также:  Не печатают принтеры после обновления windows 10

The second problem is that, even with the pseudo-signal handler support that pcntl_signal() provides, PHP can lose information about signals that occurred. If the multiple signal scenario happens, the script will not be notified that some signal happened multiple times. The larger the tick value, the more likely this can happen, especially on a busy system.

Windows, for the most part, doesn’t really use signals. There is the SetConsoleCtrlHandler() function which exists to capture Ctrl+C and Ctrl+Break and is roughly equivalent to SIGINT. The downsides are that there has to be a console attached to the process for it to work and can’t be sent by other processes. The TerminateProcess() function is equivalent to SIGKILL, which can’t be blocked/handled under other OSes and the SIGKILL signal doesn’t actually arrive at the target process. Other than those two functions/signals, there’s very little in common. Ultimately, Windows is a very different beast under the hood.

The only reason to look at signals is for some sort of long-running PHP process — a task that everyone seems to say that the language isn’t suitable for (I completely disagree, but that’s a different discussion). As I learned about the limitations of signal support in PHP even under POSIX OSes, I decided that they weren’t really the answer to my situation. The correct solution is to ignore signals altogether. For SIGINT, command-line scripts should be written to handle the scenario of premature termination — that is, they should be idempotent. In the world of PHP, signals are largely irrelevant as there are other, more flexible, and richer solutions including named mutexes/events, sockets, files, named pipes, shared memory, Service Manager, etc.

How do I send a signal to Perl on Windows?

I have some perl code which establishes a signal handler:

I’m tasked with porting this to windows and I was wondering how I could generate this signal from a C# class.

I saw the Process.Kill method in the System.Diagnostics.Process class which seems to allow me to create (via another method) and kill my process, but I can’t figure out how get it to send the signal to the perl script.

and TerminateProcess are awfully similar to a bullet in the brain. There’s no response possible. – Ben Voigt Sep 11 ’10 at 1:26

2 Answers 2

You’re probably thinking of the TERM signal handler, since KILL can’t be caught. Anyway, Windows doesn’t use signals and while it lets you use them, it’s within a single thread only, no sending signals to other processes.

You have a variety of other IPC mechanisms though, the usual one for requesting that another process exit gracefully is PostMessage(WM_QUIT) , but that’s really only applicable to graphical applications which Perl scripts usually aren’t.

A well supported approach on Windows would be for the parent process to create an event (with the inheritable flag) and pass the handle to the child process, putting it into the environment would be very convenient for Perl. Then the child can perform an action in response to the event.

In addition to window message and kernel events you could use any of sockets, pipes, files, mailslots, process exit codes, shared memory, registry entries, and DDE to communicate between processes on Windows.

Читайте также:  Linux ifconfig restart network

Can I send a ctrl-C (SIGINT) to an application on Windows?

I have (in the past) written cross-platform (Windows/Unix) applications which, when started from the command line, handled a user-typed Ctrl — C combination in the same way (i.e. to terminate the application cleanly).

Is it possible on Windows to send a Ctrl — C /SIGINT/equivalent to a process from another (unrelated) process to request that it terminate cleanly (giving it an opportunity to tidy up resources etc.)?

17 Answers 17

The closest that I’ve come to a solution is the SendSignal 3rd party app. The author lists source code and an executable. I’ve verified that it works under 64-bit windows (running as a 32-bit program, killing another 32-bit program), but I’ve not figured out how to embed the code into a windows program (either 32-bit or 64-bit).

After much digging around in the debugger I discovered that the entry point that actually does the behavior associated with a signal like ctrl-break is kernel32!CtrlRoutine. The function had the same prototype as ThreadProc, so it can be used with CreateRemoteThread directly, without having to inject code. However, that’s not an exported symbol! It’s at different addresses (and even has different names) on different versions of Windows. What to do?

Here is the solution I finally came up with. I install a console ctrl handler for my app, then generate a ctrl-break signal for my app. When my handler gets called, I look back at the top of the stack to find out the parameters passed to kernel32!BaseThreadStart. I grab the first param, which is the desired start address of the thread, which is the address of kernel32!CtrlRoutine. Then I return from my handler, indicating that I have handled the signal and my app should not be terminated. Back in the main thread, I wait until the address of kernel32!CtrlRoutine has been retrieved. Once I’ve got it, I create a remote thread in the target process with the discovered start address. This causes the ctrl handlers in the target process to be evaluated as if ctrl-break had been pressed!

The nice thing is that only the target process is affected, and any process (even a windowed process) can be targeted. One downside is that my little app can’t be used in a batch file, since it will kill it when it sends the ctrl-break event in order to discover the address of kernel32!CtrlRoutine.

(Precede it with start if running it in a batch file.)

I have done some research around this topic, which turned out to be more popular than I anticipated. KindDragon’s reply was one of the pivotal points.

I wrote a longer blog post on the topic and created a working demo program, which demonstrates using this type of system to close a command line application in a couple of nice fashions. That post also lists external links that I used in my research.

In short, those demo programs do the following:

  • Start a program with a visible window using .Net, hide with pinvoke, run for 6 seconds, show with pinvoke, stop with .Net.
  • Start a program without a window using .Net, run for 6 seconds, stop by attaching console and issuing ConsoleCtrlEvent

Edit: The amended solution from KindDragon for those who are interested in the code here and now. If you plan to start other programs after stopping the first one, you should re-enable Ctrl-C handling, otherwise the next process will inherit the parent’s disabled state and will not respond to Ctrl-C.

Also, plan for a contingency solution if AttachConsole() or the sent signal should fail, for instance sleeping then this:

I guess I’m a bit late on this question but I’ll write something anyway for anyone having the same problem. This is the same answer as I gave to this question.

Читайте также:  Как запустить терминал linux с правами администратора

My problem was that I’d like my application to be a GUI application but the processes executed should be run in the background without any interactive console window attached. I think this solution should also work when the parent process is a console process. You may have to remove the «CREATE_NO_WINDOW» flag though.

I managed to solve this using GenerateConsoleCtrlEvent() with a wrapper app. The tricky part is just that the documentation is not really clear on exactly how it can be used and the pitfalls with it.

My solution is based on what is described here. But that didn’t really explain all the details either and with an error, so here is the details on how to get it working.

Create a new helper application «Helper.exe». This application will sit between your application (parent) and the child process you want to be able to close. It will also create the actual child process. You must have this «middle man» process or GenerateConsoleCtrlEvent() will fail.

Use some kind of IPC mechanism to communicate from the parent to the helper process that the helper should close the child process. When the helper get this event it calls «GenerateConsoleCtrlEvent(CTRL_BREAK, 0)» which closes down itself and the child process. I used an event object for this myself which the parent completes when it wants to cancel the child process.

To create your Helper.exe create it with CREATE_NO_WINDOW and CREATE_NEW_PROCESS_GROUP. And when creating the child process create it with no flags (0) meaning it will derive the console from its parent. Failing to do this will cause it to ignore the event.

It is very important that each step is done like this. I’ve been trying all different kinds of combinations but this combination is the only one that works. You can’t send a CTRL_C event. It will return success but will be ignored by the process. CTRL_BREAK is the only one that works. Doesn’t really matter since they will both call ExitProcess() in the end.

You also can’t call GenerateConsoleCtrlEvent() with a process groupd id of the child process id directly allowing the helper process to continue living. This will fail as well.

I spent a whole day trying to get this working. This solution works for me but if anyone has anything else to add please do. I went all over the net finding lots of people with similar problems but no definite solution to the problem. How GenerateConsoleCtrlEvent() works is also a bit weird so if anyone knows more details on it please share.

How to send a signal to a process in C?

I need to send a signal to a process and when the process receives this signal it does some things, how is this best achieved in C?

3 Answers 3

The way to send a signal to a process is kill(pid, signal); However, you should be aware that signals are not a robust means of inter-process communication except for parent-to-direct-child messages due to inherent race conditions. Pipes, files, directories, named semaphores, sockets, shared memory, etc. all provide greatly superior approaches to inter-process communication.

If you happen to be on one of the Unix variants, the following man pages will help:

kill + fork runnable POSIX example

Time for some fun:

Compile and run:

But beware that there are many complexities when dealing with signals:

  • only certain functions can be called from signal handlers: Why only async-signal-safe functions can be called from signal handlers safely?
  • different functions have different behaviors when interrupted by signals: man 7 signal , SA_RESTART
  • global variables can only be accessed from the signal handler if they have type sig_atomic_t : How does sig_atomic_t actually work?
Оцените статью