3

I have an application in which I iterate over an array of threads, each of which needs to be sent a specific signal. In Linux, this would look something like the following:

// my_threads is a vector of std::thread objects
for (auto i = my_threads.begin(); i != my_threads.end(); i++) {
    pthread_kill(i->native_handle(), SIGPROF);
}

I am looking for the equivalent logic in Windows. That is, I want to be able to iterate over an array of std::thread objects in a Windows environment, and send them each a specific type of signal.

You can assume that I have access to std::thread::native_handle for all threads in the loop, and that I am using the C++11 standard.

After I implement this, I would imagine the code would look something like this

// my_threads is a vector std::thread objects
for (auto i = my_threads.begin(); i != my_threads.end(); i++) {
    #ifdef WIN32
        // **How do I do this?**
        WINDOWS_SIGNAL(i->native_handle(), SIGPROF);
    #else
        pthread_kill(i->native_handle(), SIGPROF);
    #endif
}

I have looked for relevant Microsoft docs, and other SO posts, but haven't found anything even remotely relevant other than this tangentially related SO post.

Community
  • 1
  • 1
Byte Lab
  • 1,576
  • 2
  • 17
  • 42
  • There is no simple way in MS Windows to do this. Windows has no equivalent to Posix Signals. – Richard Critten May 22 '16 at 18:48
  • 1
    @RichardCritten this seems to suggest otherwise: https://msdn.microsoft.com/en-us/library/xdkz3x12.aspx ? – Byte Lab May 22 '16 at 18:55
  • 3
    Windows Asynchronous Procedure Calls looks an awful lot like a generic equivalent of POSIX signals. That is to say, run a function in a particular thread context, on the top of its stack. This will be how POSIX signals are emulated. However, if you're sending 'SIGPROF`, I suspect Windows uses an entirely different paradigm than sending a signal to the thread in question. - https://msdn.microsoft.com/en-gb/library/windows/desktop/ms681951(v=vs.85).aspx – marko May 22 '16 at 19:35
  • 4
    To clarify, the Windows C runtime implements the minimum signal support required by the language, which doesn't include cross-process (or even cross-thread) signalling. (It also implements control-C handling, but in a non-standard way.) User-mode APCs are vaguely similar to signals, but are synchronous; the APC function will only be called when the thread calls SleepEx() or one of a handful of other functions that result in an alertable wait. (And no, the C runtime does not use APCs to emulate signals.) – Harry Johnston May 22 '16 at 22:36
  • We'll need more information about what the threads are doing and how they need to respond to the signal in order to provide an informed answer, but [one simple option is to use event objects.](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686915(v=vs.85).aspx) – Harry Johnston May 22 '16 at 22:39
  • @HarryJohnston Thanks for the information. Unfortunately, the use case is exactly that of a POSIX signal. That is, a set of threads are running concurrently (potentially in parallel), and I must be able to "signal" those threads from a master thread, and have them run some callback / signal handler asynchronously. – Byte Lab May 23 '16 at 00:33
  • That's not possible. But, generally speaking, anything that you could (legitimately) do from an asynchronous callback can be done some other way. – Harry Johnston May 23 '16 at 01:00
  • 2
    You can pause the thread with *SuspendThread*, save its state via *GetThreadContext*, change the registers accordingly to point to the signal handler, and resume the thread with *SetThreadContext* and *ResumeThread*. – IS4 Mar 18 '18 at 15:47
  • 1
    @HarryJohnston "the APC function will only be called when the thread calls SleepEx() or one of a handful of other functions that result in an alertable wait" => no longer true if you send a special user APC using `QueueUserAPC2` with `QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC` flag. Special user APCs run straight away (if the thread is in user mode), the thread doesn't have to be in alertable state. (If the thread is in a non-interruptible system call, it will be delivered upon return to user space.) So that is much closer semantics to signals in POSIX and pthreads – Simon Kissane Jan 28 '23 at 19:54
  • @SimonKissane, good point, though there are a couple of caveats: firstly, if I'm understanding the documentation for `QUEUE_USER_APC_FLAGS` correctly, special user APCs are only available in Windows 11. Secondly, if the thread is performing a non-alertable wait, the APC won't be delivered until the wait exits, which could be indefinitely far in the future depending on circumstances. – Harry Johnston Jan 29 '23 at 10:21
  • 1
    @HarryJohnston: The `QueueUserAPC2` API is new in Windows 11, but Special User APCs were added in Windows 10 RS5 (October 2018 Update, Build 1809). In Windows 10, you need to pass `QueueUserApcFlagsSpecialUserApc` flag to `NtQueueApcThreadEx`. `QueueUserAPC2` is just a wrapper around `NtQueueApcThreadEx` (or the new `NtQueueApcThreadEx2` call added in Win11). This page has a good writeup – https://repnz.github.io/posts/apc/user-apc/ – Simon Kissane Jan 29 '23 at 11:15

0 Answers0