如何将取消请求从 main() 发送到线程?
How to send cancelation request from main() to thread?
我需要在 thread_B 中阻止 Ctrl+C
信号(SIGINT
)并且 main() 应该处理 SIGINT
信号,所以每当用户按下 Ctrl+C
main() 应该尝试取消 thread_B 但 thread_B 需要在前 100 秒内忽略任何取消请求,任何取消请求都应在 100 秒后以及 thread_B 终止后 main() 应该被接受终止,到目前为止,我能够在 thread_B 中阻止信号,但无法从 main() 向 thread_B 发送取消请求,我该如何解决这个问题?
编辑:
当线程运行在while循环SIGINT
被禁用时,它不会接受任何Ctrl+C
请求,所以它会永远循环,main()
将如何中断while循环以便它可以向线程发送取消请求?对此有何看法?
代码:
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <math.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static volatile sig_atomic_t doneflag = 0;
/* ARGSUSED */
static void setdoneflag(int signo) {
doneflag = 1;
}
static void *
thread_func(void *ignored_argument)
{
int s;
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigprocmask(SIG_BLOCK, &sigset, NULL);
while (!doneflag)
{
sleep(1);
printf("Hello\n");
s = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
if (s != 0)
handle_error_en(s, "pthread_setcancelstate");
printf("thread_func(): started; cancellation disabled\n");
sleep(5);
printf("thread_func(): about to enable cancellation\n");
s = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
if (s != 0)
handle_error_en(s, "pthread_setcancelstate");
/* sleep() is a cancellation point */
sleep(10); /* Should get canceled while we sleep */
// /* Should never get here */
// printf("thread_func(): not canceled!\n");
}
return NULL;
}
int
main(void)
{
pthread_t thr;
void *res;
int s;
sigset_t sigset;
int recvdSig;
sigwait(&sigset,&recvdSig);
s = pthread_create(&thr, NULL, &thread_func, NULL);
if (s != 0)
handle_error_en(s, "pthread_create");
//sleep(2); /* Give thread a chance to get started */
if( recvdSig == SIGINT )
{
printf("main(): sending cancellation request\n");
s = pthread_cancel(thr);
if (s != 0)
handle_error_en(s, "pthread_cancel");
}
struct sigaction act;
act.sa_handler = setdoneflag; /* set up signal handler */
act.sa_flags = 0;
if ((sigemptyset(&act.sa_mask) == -1) || (sigaction(SIGINT, &act, NULL) == -1))
{
perror("Failed to set SIGINT handler");
return 1;
}
/* Join with thread to see what its exit status was */
s = pthread_join(thr, &res);
if (s != 0)
handle_error_en(s, "pthread_join");
if (res == PTHREAD_CANCELED)
printf("main(): Terminated\n");
else
printf("main(): thread wasn't canceled (shouldn't happen!)\n");
exit(EXIT_SUCCESS);
}
您没有将取消从 main() 发送到 pthread。信号处理程序将执行此操作。 main() 将继续,直到它收到来自信号处理程序的相同通知。
见下文...
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>
static bool shutdown;
static bool thread_finished;
pthread_t thread;
void *thread_func(void *ptr) {
while (!shutdown) {
int countdown = 5;
while (!shutdown && countdown--) {
usleep(250 * 1000);
}
printf("Still waiting...\n");
}
printf("Shutdown signal flag set. Closing.");
thread_finished = true;
return 0;
}
void sigint_handler(int sig) {
if (sig == SIGINT) { // handle shutdown
// If you need to bypass then do it here
printf("Sending shutdown signal to thread\n");
shutdown = true;
pthread_join(thread, NULL);
}
}
int main()
{
signal(SIGINT, sigint_handler);
printf("Starting background thread!\n");
shutdown = false;
thread_finished = false;
pthread_create(&thread, NULL, &thread_func, (void*)0);
while (!shutdown && !thread_finished) {
usleep(1500 * 1000);
printf("Still running from main\n");
}
return 0;
}
您可以使用相同的机制在您的应用程序最终自行退出之前关闭多个线程。
我需要在 thread_B 中阻止 Ctrl+C
信号(SIGINT
)并且 main() 应该处理 SIGINT
信号,所以每当用户按下 Ctrl+C
main() 应该尝试取消 thread_B 但 thread_B 需要在前 100 秒内忽略任何取消请求,任何取消请求都应在 100 秒后以及 thread_B 终止后 main() 应该被接受终止,到目前为止,我能够在 thread_B 中阻止信号,但无法从 main() 向 thread_B 发送取消请求,我该如何解决这个问题?
编辑:
当线程运行在while循环SIGINT
被禁用时,它不会接受任何Ctrl+C
请求,所以它会永远循环,main()
将如何中断while循环以便它可以向线程发送取消请求?对此有何看法?
代码:
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <math.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static volatile sig_atomic_t doneflag = 0;
/* ARGSUSED */
static void setdoneflag(int signo) {
doneflag = 1;
}
static void *
thread_func(void *ignored_argument)
{
int s;
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigprocmask(SIG_BLOCK, &sigset, NULL);
while (!doneflag)
{
sleep(1);
printf("Hello\n");
s = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
if (s != 0)
handle_error_en(s, "pthread_setcancelstate");
printf("thread_func(): started; cancellation disabled\n");
sleep(5);
printf("thread_func(): about to enable cancellation\n");
s = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
if (s != 0)
handle_error_en(s, "pthread_setcancelstate");
/* sleep() is a cancellation point */
sleep(10); /* Should get canceled while we sleep */
// /* Should never get here */
// printf("thread_func(): not canceled!\n");
}
return NULL;
}
int
main(void)
{
pthread_t thr;
void *res;
int s;
sigset_t sigset;
int recvdSig;
sigwait(&sigset,&recvdSig);
s = pthread_create(&thr, NULL, &thread_func, NULL);
if (s != 0)
handle_error_en(s, "pthread_create");
//sleep(2); /* Give thread a chance to get started */
if( recvdSig == SIGINT )
{
printf("main(): sending cancellation request\n");
s = pthread_cancel(thr);
if (s != 0)
handle_error_en(s, "pthread_cancel");
}
struct sigaction act;
act.sa_handler = setdoneflag; /* set up signal handler */
act.sa_flags = 0;
if ((sigemptyset(&act.sa_mask) == -1) || (sigaction(SIGINT, &act, NULL) == -1))
{
perror("Failed to set SIGINT handler");
return 1;
}
/* Join with thread to see what its exit status was */
s = pthread_join(thr, &res);
if (s != 0)
handle_error_en(s, "pthread_join");
if (res == PTHREAD_CANCELED)
printf("main(): Terminated\n");
else
printf("main(): thread wasn't canceled (shouldn't happen!)\n");
exit(EXIT_SUCCESS);
}
您没有将取消从 main() 发送到 pthread。信号处理程序将执行此操作。 main() 将继续,直到它收到来自信号处理程序的相同通知。
见下文...
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>
static bool shutdown;
static bool thread_finished;
pthread_t thread;
void *thread_func(void *ptr) {
while (!shutdown) {
int countdown = 5;
while (!shutdown && countdown--) {
usleep(250 * 1000);
}
printf("Still waiting...\n");
}
printf("Shutdown signal flag set. Closing.");
thread_finished = true;
return 0;
}
void sigint_handler(int sig) {
if (sig == SIGINT) { // handle shutdown
// If you need to bypass then do it here
printf("Sending shutdown signal to thread\n");
shutdown = true;
pthread_join(thread, NULL);
}
}
int main()
{
signal(SIGINT, sigint_handler);
printf("Starting background thread!\n");
shutdown = false;
thread_finished = false;
pthread_create(&thread, NULL, &thread_func, (void*)0);
while (!shutdown && !thread_finished) {
usleep(1500 * 1000);
printf("Still running from main\n");
}
return 0;
}
您可以使用相同的机制在您的应用程序最终自行退出之前关闭多个线程。