等待信号,然后继续执行

2024-01-17

我正在尝试制作一个程序suspends它的执行直到信号到达。然后,信号到达后我只想我的代码从原来的地方继续执行。我不希望它执行函数处理程序或任何其他内容。有没有一种简单的方法可以做到这一点?我已经奋斗了一周左右,到处阅读,但没有设法获得完全可操作的代码。

特别是,我希望主程序创建一个线程等待某些特定事件发生(例如,用户已将一些数据输入到标准输入)。与此同时,主程序正在做某事,但在某个时候它会暂停执行,直到收到信号。

The signal可能来自线程,因为它已检测到event或者可能是由于timeout因为我不想让它永远等待。

我已经编写了一些代码,但它没有按预期工作......

/*
 * This code SHOULD start a thread that gets messages from stdin.
 *  If the message is a "quit", the thread exits. Otherwise it raises
 *  a signal that should be caught by the main program.
 *  The main program simply waits for the message unless a timer of
 *  5.5 seconds expires before receiving the signal from the thread.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
#include <signal.h>

#define BSIZE 100   /* Buffer size */

sigset_t mask;              
pthread_t tid;
//struct itimerval timervalue;

int milisec = 5500; /* Timeout: 5,5 seconds */
int end = 0;

char buffer[BSIZE];


//Function prototypes
void init(void);
void * thread_job(void *);
void message_rcvd(void);
void wait_for_message_or_timeout(void);
int start_timer(struct itimerval, int);
int stop_timer(struct itimerval);
void on_signal(int);


// MAIN: Wait for message or timeout
int main(int argc, char ** argv) {

    init();

    while(!end){
        wait_for_message_or_timeout();
        if(!end)
            printf("Message received [%s]\n", buffer);
    }

    return 0;
}


// INIT: Initializes the signals that the program will wait for
//       and creates a thread that will eventually generate a signal
void init()
{

    /* Init the signals I want to wait for with sigwait() */
    sigemptyset(&mask);         
    sigaddset(&mask, SIGUSR1);  
    sigaddset(&mask, SIGALRM);
    sigprocmask(SIG_BLOCK, &mask, NULL);

    //signal(SIGUSR1, SIG_IGN);
    signal(SIGUSR1, on_signal);

    /* Create the thread and put it to work */
    pthread_t tid;
    pthread_create(&tid, NULL, thread_job, NULL);

}

void on_signal(int signum){
    printf("on_signal\n");
}

// THREAD CODE -------------
// THREAD JOB: When the user inputs a message, it passes the message
//              to the main thread by invoking message_rcvd()
void * thread_job(){

    int end = 0;

    while(!end){
        printf("Input message:");
        if (fgets(buffer, BSIZE, stdin) != NULL)
            message_rcvd();
    }
}

// MESSAGE RECEIVED: If message is not equal to "quit" raise a signal
void message_rcvd(){

    if(strcmp(buffer, "quit") == 0){
        exit(0);
    }else{
        printf("Going to raise SIGUSR1...");
        if(raise(SIGUSR1) == 0)
            printf("raised!\n");
    }

}


// WAIT: Should wait for signal SIGUSR1 for some time
void wait_for_message_or_timeout(){

    int sigid;  
    struct itimerval t;

    /* Set a timer to prevent waiting for ever*/
    printf("Setting timer...\n");
    start_timer(t, milisec);

    /* Put the process to wait until signal arrives */
    sigwait(&mask, &sigid);

    switch(sigid){
        case SIGUSR1:
                printf("Received SIGUSR1: Message avaible!\n");
                break;
        case SIGALRM:
                printf("Received SIGALRM: Timeout\n");
                end = 1;
                break;
        default:
                printf("Unknown signal received\n");
                break;
    }

    printf("Stopping timer...\n");
    /* Stop timer */
    stop_timer(t);
}

// START TIMER: I don't want the timer to cause the execution
//              of a handler function 
int start_timer(struct itimerval timervalue, int msec)
//int start_timer(int msec)
{

  timervalue.it_interval.tv_sec = msec / 1000;
  timervalue.it_interval.tv_usec = (msec % 1000) * 1000;
  timervalue.it_value.tv_sec = msec / 1000;
  timervalue.it_value.tv_usec = (msec % 1000) * 1000;

  if(setitimer(ITIMER_REAL, &timervalue, NULL))
  {
    printf("\nsetitimer() error\n");
    return(-1);
  }
  return(0);
}

// STOP TIMER: 
int stop_timer(struct itimerval timervalue)
//int stop_timer()
{
  timervalue.it_interval.tv_sec = 0;
  timervalue.it_interval.tv_usec = 0;
  timervalue.it_value.tv_sec = 0;
  timervalue.it_value.tv_usec = 0;

  if(setitimer(ITIMER_REAL, &timervalue, NULL))
  {
    printf("\nsetitimer() error\n");
    return(-1);
  }
  return(0);

}

这是此代码的典型执行。

./signaltest 
Setting timer...
Input message:hello
Going to raise SIGUSR1...raised!
Input message:friend
Going to raise SIGUSR1...raised!
Input message:Received SIGALRM: Timeout
Stopping timer...

正如您所看到的,信号 SIGUSR1 正在被引发,并且 sigwait 正在被解除阻塞。但是,在发出信号后,代码似乎不再继续。 (请注意,我不需要信号处理程序,但我只是出于调试目的添加了信号处理程序。我已使用以下命令阻止了它的执行sigprocmask)

为什么 SIGUSR1 解除了 sigwait 的阻塞,但执行不从那里继续?有什么办法可以让解封后继续使用吗?这似乎适用于 SIGALRM,但为什么不适用于 SIGUSR1?

正如我所说,我一直在查看大量的 stackoverflow 问题、在线指南,尝试使用不同的系统调用(例如,暂停、sigsuspend),...但找不到解决此问题的方法:-(

如果您想知道为什么我不通过不使用线程来更简单地执行此代码,是因为这实际上不是我正在实现的代码,而只是一个更简单的示例,以使我的问题更清楚。我实际上正在尝试实现一个网络协议 API,类似于我自己的协议的套接字 API。

提前致谢


The SIGUSR1信号没有到达您认为的位置。

在多线程程序中,raise函数发送信号到当前线程, 哪一个是thread_job在这种情况下线程。所以主线程永远不会看到信号。

您需要保存主线程的线程ID,然后使用pthread_kill向该线程发送信号。

添加一个新的全局:

pthread_t main_tid;

然后将其填充到您的init功能在开始新线程之前:

void init()
{
    main_tid = pthread_self();
    ...

Then in message_rcvd, use pthread_kill:

    if(pthread_kill(main_tid, SIGUSR1) == 0)
        printf("raised!\n");

另外,删除以下定义end in thread_job,并删除定义tid in init。这些定义掩盖了同名的全局变量。

示例输出:

Setting timer...
Input message:hello
Going to raise SIGUSR1...raised!
Input message:Received SIGUSR1: Message avaible!
Stopping timer...
Message received [hello
]
Setting timer...
test
Going to raise SIGUSR1...raised!
Input message:Received SIGUSR1: Message avaible!
Stopping timer...
Message received [test
]
Setting timer...
Received SIGALRM: Timeout
Stopping timer...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

等待信号,然后继续执行 的相关文章

  • 如何向 UWP 项目添加 .NET dll 引用?

    我有几个适用于 NETv4 x 的 NET dll 项目 我将版本更改为 4 6 1 并重新构建 没有出现问题 当我尝试从 UWP 项目向它们添加引用时 出现错误 项目的目标是 NETCore 而文件引用的目标是 NET框架 这不是受支持的
  • 如何从当前 .NET 表单/应用程序发送密钥 F12

    我非常确定以下按钮激活的表单代码应该在我的 C 应用程序中引发 Control F12 SendKeys F12 但它似乎并没有继续进入 Windows shell 并激活另一个正在侦听它的程序 我的键盘可以用 看起来发送键在某处被拦截 并
  • 将 2D 数组映射到 1D 数组

    我想用一维数组来表示一个二维数组 函数将传递两个索引 x y 和要存储的值 这两个索引代表一维数组的单个元素 并相应地设置它 我知道一维数组需要具有 arrayWidth arrayHeight 的大小 但我不知道如何设置每个元素 例如 如
  • boost线程在中断时不打印退出消息

    我有这段代码用于执行三个线程 其中第二个线程应在按 Enter 时中断并打印退出消息 void input val DO STUFF return void process val DO STUFF try cout lt lt waiti
  • 阅读 Stack Overflow RSS 源

    我正在尝试获取未回答问题的列表the feed https stackoverflow com feeds 但我在阅读时遇到困难 const string RECENT QUESTIONS https stackoverflow com f
  • 使用 VSTO 更改 Outlook 设置

    我刚刚花了大约 4 个小时试图弄清楚如何以编程方式检索 设置 Microsoft Outlook 2010 的 Outlook 设置 我所说的 设置 是指文件 选项 邮件下的设置 我想做的是检索用户设置的设置列表 自动化我们每天需要在某些消
  • 控制台应用程序 .net Core 2.0 的配置

    在 net Core 1 中我们可以这样做 IConfiguration config new ConfigurationBuilder AddJsonFile appsettings json true true Build 这样就可以使
  • 为什么以下代码不允许我使用 fgets 获取用户输入但可以使用 scanf?

    这是一个更大程序的简短摘录 但该程序的其余部分无关紧要 因为我认为我能够隔离该问题 我怀疑这与我使用 fgets 的方式有关 我读过 最好使用 fgets 而不是 scanf 但我似乎无法让它在这里正常工作 当我使用以下代码时 程序不会给我
  • 使用 Linq 进行异步Where过滤

    我有一个List通过填充的元素async调用 WebService 没问题 我需要过滤该列表以便在应用程序视图上显示某些内容 我试过这个 List
  • 标准 C 中的 sizeof 与 sizeof()? [复制]

    这个问题在这里已经有答案了 我看到一些直接使用 sizeof 的代码 想知道它是否是标准 C 令我惊讶的是 它运行得很好 这是一个例子 include
  • 使用 AutoMapper 进行 LINQ GroupBy 聚合

    试图让查询工作 但老实说不确定如何 或者是否可能 进行它 因为我尝试过的一切都不起作用 共查询6个表 Person PersonVote PersonCategory Category City FirstAdminDivision Per
  • 如何在 C++ 中使用 PI 常数

    我想在一些 C 程序中使用 PI 常数和三角函数 我得到三角函数include
  • 如何使用 Clang 查找内存泄漏

    我在我的机器 ubuntu 中安装了 Clang 以便发现我的 C 代码中的内存泄漏 我编写了一个示例代码来检查它的工作情况 如下所示 File hello c for leak detection include
  • 编写专门用于类及其子类的函数模板

    我正在尝试编写一个函数模板 一个版本应该用于不满足另一版本标准的所有类型 当参数是给定类的基类或该类本身时 应使用另一个版本 我尝试过超载Base 但是当类派生自Base 他们使用通用的 而不是特定的 我也尝试过这种 SFINAE 方法 s
  • 用 C# 编写的带有点击移动的 WPF 游戏

    我试图将标签网格移动到鼠标的位置 就像冒险游戏中的移动一样 理想情况下 我会在途中删除并重新绘制它们 但是 现在我只想弄清楚如何将 int 转换为厚度或 pointtoscreen 到目前为止我有 player XMove int Mous
  • 为什么我不能在扩展 List 的类中调用 OrderBy?

    我有一堂课 Deck 其中包含一个名为的方法Shuffle 我正在致力于重构Deck延长List
  • 如何仅更改 DateTime 的日期部分,同时保留时间部分?

    我在代码中使用了很多 DateTime 我想将这些日期时间更改为我的特定日期并保留 时间 1 2012 02 02 06 00 00 gt 2015 12 12 06 00 00 2 2013 02 02 12 00 00 gt 2015
  • Windows 上 libcurl 的静态库[重复]

    这个问题在这里已经有答案了 如何将此库 libcurl 静态链接到 exe 我努力了 disable share enable static 没有帮助 我使用的是MingW32 有没有一种简单的方法来静态链接这个库 这样我的应用程序就不再有
  • 在 C# 中读取/写入命令行程序

    我正在尝试与 C 的命令行程序进行对话 它是一个情绪分析器 它的工作原理如下 CMD gt java jar analyser jar gt Starting analyser 这是我想从我的 C 程序插入内容的地方 例如 I love y
  • 最后从同一类中的其他构造函数调用构造函数

    我在这里读到可以调用另一个构造函数从同一类中的另一个构造函数调用构造函数 https stackoverflow com questions 829870 calling constructor from other constructor

随机推荐

  • 有权在 Django 管理中仅修改模型的一个字段的用户

    我有一个名为专家用户谁应该只能在 Django 管理中修改用户的调用模型 金钱 的属性 我尝试使用以下命令在模型中添加权限Meta但是当获得该许可进入时我无法修改任何内容 因为我无权访问任何用户 我的模型是这样的 class Client
  • 选择更改事件触发多次

    下拉列表的 更改 事件发生了非常奇怪的事情 基本上我有一个下拉菜单 在更改它时我必须进行一些跨域 Web 服务调用 这个调用是由 javascript 本身进行的 当我第一次更改 选择 列表中的项目时 更改事件仅触发一次 下次再做两次 就长
  • 对curl对象的未定义引用

    已编辑 我几周来一直试图让curl从网页调用信息 但我得到了一个看似常见的错误 即我的程序无法识别curl对象 C Users CurlAttempt CurlAttempt1 cpp 25 undefined reference to i
  • NotReadableError:无法启动源

    我在我的项目中添加了这段代码 if navigator mediaDevices undefined navigator mediaDevices if navigator mediaDevices getUserMedia undefin
  • 让 System.Web.Optimization 在类库中的剃刀视图中工作

    我正在构建一个模块化 MVC4 应用程序 其中每个模块 区域 都是一个类库 模型和控制器编译成 dll 视图被复制到适当的文件夹中 在运行时 一切正常 在设计时 还剩下一个恼人的问题 在类库中编辑剃刀视图时 Visual Studio 无法
  • 使用 UUID npm 模块出现奇怪的错误。我究竟做错了什么?

    Getting 错误 D test node modules uuid 的包导出未定义 子路径 一直当我require it 操作系统 Windows 10 专业版节点版本 v13 1 0NPM 版本 6 14 4 我从头开始创建了一个项目
  • C# datagridview 单元格具有自动完成功能,例如

    我正在尝试为我的商店创建一个桌面应用程序 我的应用程序当前使用自动完成项目 如截图所示 现在我想将该单元格更改为自动完成LIKE功能 例如 我的项目列表包含 book brush pen samsung note 1 samsung not
  • 使用 selenium webdriver 在自定义下拉列表中选择一个选项

    我正在尝试使用 selenium java 从 DropDown 中选择一个选项 我也尝试过很多解决方案 在 FirePath 中执行 XPath 时找到国家元素 但在运行脚本时找不到 硒代码 driver findElement By x
  • 将代码附加到现有函数的末尾

    每当函数 foo 触发时 我需要触发函数 bar 我无法控制函数 foo 或它将来是否会改变 我经常遇到这种情况 而且我讨厌它 我编写此函数是为了将代码添加到函数 foo 的末尾 function appendToFunction fn c
  • 在java中从数据库中检索值

    我正在制作一个程序 从我创建的数据库中检索输入的数据 字段值 但当我运行它时 输出始终为空 我想知道怎么了 这是我的代码 import java sql public class GuestsInfo private String firs
  • 如何删除 Windows 上的 dotnet 运行时?

    我找到了命令dotnet list runtimes它为我输出 缩写 Microsoft AspNetCore All 2 1 15 C Program Files dotnet shared Microsoft AspNetCore Al
  • 如何挂钩 MySQL 查询为 true 时触发的事件?

    如何创建一个 PHP 脚本来一致地检查 MySQL 行 如果一组查询匹配 它就会启动一个事件 例如发送电子邮件 例如 在查询匹配时Fire开始电子邮件 To email protected cdn cgi l email protectio
  • 带有数组或 JSON 数据的 D3 堆积图

    我想创建一个堆积条形图 例如http bl ocks org mbostock 3886208 http bl ocks org mbostock 3886208 但我不想使用 CSV 文件 如何使用数组或 JSON 数据创建堆积图 在 c
  • 如何在 C# 3.5 中取消异步委托?

    我上下搜索了谷歌 但几乎找不到有关该主题的任何正确信息 我想做的是这样的 用户在文本框中键入单个搜索字符串 我等待 0 5 秒 然后开始 BeginInvoke 指向搜索方法的委托 如果用户再次键入一个字符 我想取消搜索并使用键入的新字符串
  • 使用大叶和熊猫的等值线图

    我在用folium创建一组国家的等值区域地图 我正在关注文档 http folium readthedocs org en latest choropleth examples 然而 由于某种原因 地图没有显示任何阴影 我正在使用来自自然地
  • 删除文本时,IE 中的 jQuery .live('input) 不起作用

    基于这个问题根据计数器的值淡入 淡出文本 https stackoverflow com questions 10780756 fade in out text based upon value of counter 我有以下标记
  • 更改 Android 上的状态栏字体颜色

    有没有办法改变 Android 上的状态栏字体和图标颜色 不讨论背景颜色 None
  • Silverlight:VisualStateManager.GetVisualStateGroups 没有,我怎样才能获得它们?

    我尝试过使用VisualStateManager GetVisualStateGroups in the OnAttached覆盖我的自定义行为 以及添加到的事件处理程序中AssociatedObject Loaded该行为中的事件 两次我
  • React Native 构建版本没有反映调试所做的更改(android)

    我对我的 React Native 应用程序进行了一些样式更改 调试中的一切看起来都很好 因此我尝试使用 react native run android variant release 运行发布变体 并且调试中没有出现任何更改 我确定我没
  • 等待信号,然后继续执行

    我正在尝试制作一个程序suspends它的执行直到信号到达 然后 信号到达后我只想我的代码从原来的地方继续执行 我不希望它执行函数处理程序或任何其他内容 有没有一种简单的方法可以做到这一点 我已经奋斗了一周左右 到处阅读 但没有设法获得完全