在 C 中使用 SIGALRM 强制函数结束

发布于 2024-10-16 19:13:04 字数 247 浏览 2 评论 0原文

现在我有一个连接到 SIGARLM 的函数,该函数会在 1 秒后关闭,并且每次都会重新报警并在另一秒后关闭。我编写的 SIGALRM 函数的逻辑中有一个测试,以查看是否已达到某个超时,以及何时达到我需要它来终止正在运行的函数。有人知道我该怎么做吗?

我忘了提及:在需要终止的函数中,它等待 scanf() 并且即使 scanf() 尚未返回,该函数也需要终止。

Right now I have a function connected to SIGARLM that goes off after 1 second and will re-alarm itself to go off in another second everytime. There's a test in the logic of the SIGALRM function I wrote to see if a certain timeout has been reached and when it does I need it to kill a function that's running. Does anybody know how I can do this?

I forgot to mention: in the function that needs to be killed it waits on scanf() and the function needs to die even if scanf() hasn't returned yet.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

南烟 2024-10-23 19:13:04

一种可能值得研究的方法是使用 select 来轮询 stdin 并查看是否有数据准备就绪。 select 允许您在文件描述符上等待一段时间,控制您何时可以被中断以及被什么中断,并且看起来在这里它是完美的。您可以坐在循环中等待最多一秒钟,然后在没有可用数据的情况下优雅地失败。这样,SIGALRM 就不需要终止该函数;它会自己处理这一切。

One approach that might be worth looking into is using select to poll stdin and see if any data is ready. select lets you wait for some period of time on a file descriptor, controlling when you can be interrupted and by what, and seems like it's perfect here. You could just sit in a loop waiting for up to a second, then failing gracefully if no data is available. That way, SIGALRM wouldn't need to kill the function; it would take care of that all by itself.

最终幸福 2024-10-23 19:13:04

不确定您到底在问什么或该程序的结构是什么。如果我理解正确的话:某个函数正在运行,如果它已经运行了 X 时间,您想终止它。您每秒都会唤醒一个 SIGALARM,它将检查其他函数的运行时间并终止。

您打算如何终止该功能?是同一个进程中的一个函数,还是一个单独的进程。您的问题是如何终止它或如何判断何时需要终止它?

我做过一些我认为类似的事情。我有一个多线程应用程序,其结构包含有关我希望监视的线程的信息。该结构包含一个成员变量“startTime”。我的监控(SIGALARM)函数可以访问线程列表。当监视器醒来时,它将遍历列表,将当前时间与每个线程的 startTime 进行比较,如果超过了允许的运行时间,则向函数发送一条消息。

这有帮助吗?

Not sure exactly what you're asking or what the structure of the program is. If I understand correctly: some function is running and you want to terminate it if it's been running for X time. You have a SIGALARM wake up every second and that will check the running time of the other function and do the terminate.

How do you plan to kill the function? Is it a function in the same process, or is it a separate process. Is your question how to terminate it or how to tell when it needs to be terminated?

I've done something which I believe is similar. I had a multi-threaded application with a structure which contained information about the threads I wished to monitor. The structure contained a member variable "startTime". My monitoring (SIGALARM) function had access to a list of threads. When the monitor woke up it would traverse the list, compare current time to each thread startTime and send a message to the function if it had exceeded it's allowed runtime.

Does this help at all?

地狱即天堂 2024-10-23 19:13:04

您可以使用(全局)变量在信号处理程序和应停止的函数之间进行通信。然后该函数将检查该变量以查看它是否仍应继续运行或是否应退出。

有这样一行:

volatile int worker_expired = 0;

void worker() {
   while (!worker_expired) {
      // ...
   }
}

void sig_alrm() {
   worker_expired = 1;
}

You could use a (global) variable to communicate between the signal handler and the function that should be stopped. The function then would check that variable to see if it should still continue running or if it should exit.

Something line this:

volatile int worker_expired = 0;

void worker() {
   while (!worker_expired) {
      // ...
   }
}

void sig_alrm() {
   worker_expired = 1;
}
开始看清了 2024-10-23 19:13:04

如果您希望信号终止 IO 操作,则需要确保它是一个中断信号处理程序。在现代系统上,除非您另有指定,否则被信号中断的系统调用会自动重新启动。如果您想控制此类事情,请使用 sigaction 函数而不是 signal 函数来设置信号处理程序。使用sigaction,除非您指定SA_RESTART,否则信号处理程序可以中断。

如果您使用像 read 这样的文件描述符 IO 函数,您现在应该会获得您想要的效果。

如果您使用 fscanfstdio 函数,被信号中断将使 FILE 进入错误状态,只能通过clearerr,并将丢失缓冲区中的任何部分输入。中断信号不能与 stdio 很好地混合,除非您只想中止文件上的所有操作并在收到信号时将其关闭。

If you want the signal to terminate IO operations, you need to make sure it's an interrupting signal handler. On modern systems, system calls interrupted by signals automatically restart unless you specify otherwise. Use the sigaction function rather than the signal function to setup your signal handlers if you want control over things like this. With sigaction, unless you specify SA_RESTART, signal handlers can interrupt.

If you're using file-descriptor IO functions like read, you should now get the effects you want.

If you're using stdio functions like fscanf, getting interrupted by a signal will put the FILE into an error state that can only be cleared by clearerr, and will lose any partial input in the buffer. Interrupting signals do not mix very well with stdio unless you just want to abort all operations on the file and close it when a signal is received.

万水千山粽是情ミ 2024-10-23 19:13:04

所以...稍微重申一下:与其说您想要终止该函数,不如说您希望终止任何挂起的 i/o 并退出该函数。

我会:

  1. 使用 select() 定期唤醒并检查信号处理程序设置的标志。如果未设置标志并且没有待处理的输入,则循环并再次调用 select()。

  2. 我怀疑您的 SIGALARM 处理程序不仅仅检查这个计时器,因此使用 pselect() 来检查 i/o 或 SIGALARM 可能不适合您。我想知道您是否可以获取用户定义的信号,并将其传递到 pselect 中。那么你的警报处理程序将发送该用户定义的信号。

关于选择 1,如果 SIGALARM 每秒唤醒一次,那么您可以调整 select() 休眠的时间,使其在最大错误延迟范围内。换句话说,假设在调用 select() 之后立即发生超时,那么直到 select() 唤醒才能检测到 SIGALARM 处理程序设置的标志。因此,如果 select() 每秒唤醒 10 次,则可能需要 1/10 秒的时间来检测“放弃”标志的设置(由 SIGALARM 处理程序设置)。

So ... to restate slightly: it isn't so much that you want to kill the function as that you want any pending i/o to terminate and the function to exit.

I would either:

  1. use select() to periodically wake up and check a flag set by the signal handler. if the flag isn't set and there's no input pending then loop and call select() again.

  2. i suspect that your SIGALARM handler is doing more than just checking this one timer, and so using pselect() to check for i/o OR SIGALARM is probably not an option for you. i wonder if you could grab a user defined signal, and pass that in pselect. then your alarm handler would send that user defined signal.

Regarding choice 1, if SIGALARM is waking every second then you can adjust the time that select() sleeps to be within your maximum error latency. In other words assume that the timeout occurs immediately after the call to select(), then it will take until select() wakes up to detect the flag set by the SIGALARM handler. So if select() wakes up 10 times per second then it could take up to 1/10 second to detect the setting of the "give up" flag (set by the SIGALARM handler).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文