简体   繁体   English

信号处理程序在错误的线程中被调用

[英]Signal handler getting called in wrong thread

I want to know if its possible to interrupt main thread and ask it to execute some callback. 我想知道是否有可能中断主线程并要求它执行一些回调。 The main thread should continue with what it was doing after completing the callback. 完成回调后,主线程应继续执行其操作。

For instance, we have 2 threads t1 and m1 (main thread). 例如,我们有2个线程t1和m1(主线程)。 t1 will interrupt m1 (main thread) and ask it to call a function with some parameters. t1将中断m1(主线程)并要求其调用带有某些参数的函数。 The m1 (main thread) will stop doing what it was doing before and will start executing the function. m1(主线程)将停止执行之前的操作,并将开始执行该功能。 The after finishing the function, it will get back to what it was doing earlier. 完成功能后,它将返回到之前的操作。

I want to replicate what hardware interrupt does. 我想复制硬件中断的功能。 I have one thread that reads data from a file. 我有一个线程从文件中读取数据。 Then it should ask main thread to call a function. 然后,它应要求主线程调用函数。 Main thread will be doing something. 主线程将做某事。 It should stop doing it and start executing the function. 它应该停止执行并开始执行该功能。 After completing it, main thread should continue with what it was doing 完成后,主线程应继续其所做的工作

I have written following code using signals 我已经使用信号编写了以下代码

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

static void catch_function(int signo) {
    int id = GetCurrentThreadId();
    printf("\nThread ID is %d",id);
    signal(SIGINT, catch_function);
}


DWORD WINAPI MyThreadFunction( LPVOID lpParam ) 
{
    int id = GetCurrentThreadId();
    printf("\nChild Thread ID is %d",id);
    while(1)
    {
        Sleep(50);
        if (raise(SIGINT) != 0) {
            fputs("Error raising the signal.\n", stderr);
            return EXIT_FAILURE;
        }
    }
    return 0;
}


int main(void) {

    int id = GetCurrentThreadId();
    printf("\nMain Thread ID is %d",id);
    if (signal(SIGINT, catch_function) == SIG_ERR) {
        fputs("An error occurred while setting a signal handler.\n", stderr);
        return EXIT_FAILURE;
    }

    HANDLE thread;
    DWORD  threadId;
    thread = CreateThread(NULL, 0, &MyThreadFunction, NULL, 0, &threadId);
    if(!thread)
    {
        printf("CreateThread() failed");
    }

    while(1)
    {
        Sleep(50);
    }
    return 0;
}

The output of code is 代码的输出是

Main Thread ID is 6124 
Child Thread ID is 7854
Thread ID is       7854
Thread ID is       7854

So my question is should not the signal handler be called in Main thread? 所以我的问题是信号处理程序是否应该在主线程中调用? I want main thread to call the handler function not the thread which raise the signal? 我要主线程调用处理程序函数,而不是发出信号的线程? please let me know what is the correct way of achieving this. 请让我知道实现此目标的正确方法。

PS. PS。 I have to do it for both windows and linux. 我必须为Windows和Linux都这样做。

I can only offer advice from a Linux side, but as you said that was of interest too then... 我只能从Linux方面提供建议,但是正如您所说的那样,那时也很有趣...

... raise does the following (from the manual page): ... raise的确以下(从手册页):

The  raise()  function sends a signal to the calling process or thread.

So in a multi-threaded program it is the thread that calls raise that will get the signal. 因此,在多线程程序中,调用raise的线程将获得信号。

On Linux, for threading, you'll probably be using pthreads, in which case you have pthread_kill , this sends a specific signal to a specific thread. 在Linux上,对于线程化,您可能会使用pthreads,在这种情况下,您将拥有pthread_kill ,这会将特定信号发送到特定线程。 You'd need to use pthread_self in the main thread to get the thread id, then pass this to the worker thread. 您需要在主线程中使用pthread_self来获取线程ID,然后将其传递给工作线程。 The worker thread can then send signals directly to the main thread. 然后,工作线程可以直接将信号发送到主线程。

I suspect you need to find something similar for Windows, but that's not something I know about. 我怀疑您需要为Windows找到类似的东西,但这不是我所知道的。

The only one that can interrupt a thread is itself or the Task Scheduler. 唯一可以中断线程的线程本身就是任务调度程序。 If you were to stop someone else you would need direct access to timer hardware. 如果要停止其他人,则需要直接访问计时器硬件。

You can do what Ed Heal said. 您可以按照Ed Heal所说的做。 Use conditional variables and semaphores. 使用条件变量和信号量。 My advice is to build up a linked list or even just an array storing what to do and who is the one wich should do it. 我的建议是建立一个链表,甚至只是一个数组,存储要做什么以及谁应该做。

See what Windows does to send messages to the program in "event-driven UI". 查看Windows如何在“事件驱动的UI”中将消息发送到程序。 A MSG struct is given to the application with some integers, like message code, WPARAM and LPARAM. MSG结构使用一些整数(例如消息代码,WPARAM和LPARAM)提供给应用程序。

Define a structure of your own and use it to send messages to each thread (some form of interprocess communication). 定义自己的结构并将其用于将消息发送到每个线程(某种形式的进程间通信)。 And, that's important, set a timer to a callback function or keep with your Sleep(50) (or more) to not keep "bothering" your processor for nothing. 而且,重要的是,将计时器设置为回调函数,或者保持Sleep(50) (或更高),以免使处理器毫无负担。

Hope this helps and sorry for bad english. 希望这对您有所帮助,对不起英语不好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM