C:关闭多线程程序

时间:2017-10-21 19:47:28

标签: c multithreading pthreads

这个想法是让一个主线程启动多个工作线程。除了发送信号之外,没有明确的方法退出程序。但是,如果在任何地方发生错误,程序也应该干净地退出。

我试着展示到目前为止我所拥有的东西。标题没有显示,但没有它们应该很清楚。我们有一个main.c,其主要功能是一切开始的,worker.c,带有线程管理和object.c的抽象,一个工作线程的特定实现。将有多个不同的实现,但都具有相同的结构(即具有process()循环的while(running)函数。)

的main.c

#include <signal.h>

#define NUM_THREADS 5

volatile static sig_atomic_t running = 1;
volatile static int exit_code = 0;

void shutdown(int s)
{
    running = 0;
    exit_code = s;
}

int main(int argc, char **argv)
{
    struct sigaction sa;
    sa.sa_handler = shutdown;
    sigaction(SIGINT, &sa, 0);

    thread_obj *threads[NUM_THREADS];
    for (int i = 0; i < NUM_THREADS; ++i) {
        threads[i] = worker_new();
    }


    for(int i = 0; i < NUM_THREADS; ++i) {
        pthread_join(threads[i]->worker, NULL);
        theads[i]->free();
        free(threads[i]);
    }

    return exit_code;
}

worker.c

#include <pthread.h>

struct thread_object {
    pthread_t worker;
    int *running:
    void *obj;
    void (*process)(void *obj, int *running);
    void (*free)(void *obj);
}:

void *thread_func(void *obj)
{
    struct thread_object *tmp = obj;
    tmp->process(tmp->obj, tmp->running):
    return;
}

struct thread_object *worker_new(void *obj)
{
   struct thread_object *tmp = malloc(sizeof(*tmp));
   tmp->obj = obj;
   tmp->running = running;
   tmp->process = obj->process;
   tmp->free = obj->free;
   pthread_create(&(tmp->worker), NULL, thread_func, obj);
   return tmp;
}

object.c

#include "main.h"

void process(void *obj, int *running)
{
    struct special_object *tmp = obj;
    while(*running) {
        // do something
        if(error) {
            kill(getpid(), SIGTERM);
            break;
        }
    }
    // cleanup tasks
}

现在的问题是,在C中实现这个最干净,最快速和最便携的方法是什么?再两个要点:停止所有线程并正常关闭如果a)收到SIGINT之类的信号或b)至少有一名工人遇到错误。

编辑:我试图包含这些建议,但现在有一些后续问题:

  • pthread_join更多/更少/同样有效睡眠?主要的 线程与工人运行时无关,只能捕获信号, 我希望避免尽可能多的唤醒。
  • 请考虑以下内容:我们捕获SIGTERM信号,处理程序设置 running变量为false。这会跳过循环(可靠)吗?

kill(getpid(), SIGTERM); while (*running) {;}

1 个答案:

答案 0 :(得分:0)

在这种情况下,不需要睡眠循环,连接应该足够了。

在其他用例中,您可以查看带有p​​id为-1的waitpid,以从任何有话要说的线程中获取状态。

如果某些线程在其他线程之前停止,或者在线程发布之后执行某些操作或者等到所有线程都已发布,那么信号量在某些情况下也会有用。