加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 是否可以在线程中使用exit?

发布时间:2020-12-16 07:04:41 所属栏目:百科 来源:网络整理
导读:我把exit()放到一个线程中,但我的程序有时不会退出. 根据这个link,exit()不是异步信号安全的.我想知道在一个线程中使用exit()是否会导致未定义的行为. 解决方法 普通退出(例如,与_exit相反)需要执行所有通常的atexit清理,输出 – 刷新等工作.可以构造在某些
我把exit()放到一个线程中,但我的程序有时不会退出.

根据这个link,exit()不是异步信号安全的.我想知道在一个线程中使用exit()是否会导致未定义的行为.

解决方法

普通退出(例如,与_exit相反)需要执行所有通常的atexit清理,输出 – 刷新等工作.可以构造在某些情况下挂起的代码,但我不得不做一个“明显的问题”来展示它.如果库例程(例如,内部stdio fflush)试图在其他线程持有的退出线程中获取锁(例如,在stdio流上),即使没有自己的atexit也可能获得类似的挂起.既然你没有展示你的代码,我只是在猜测.

这是一个测试程序(有故意的,明显的问题),当被告知时,至少在FreeBSD上会挂起. (格式化棘手,因为剪切和粘贴保持标签,但后来我不得不编辑一些空格…)

#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

pthread_mutex_t global_mtx;

void die(int error,const char *fmt,...) {
    va_list ap;

    va_start(ap,fmt);
    vfprintf(stderr,fmt,ap);
    va_end(ap);
    if (error)
        fprintf(stderr,": %sn",strerror(error));
    else
        putc('n',stderr);
    fflush(stderr);
    _exit(0);
}

enum behavior { NORMAL,EXIT_WO_HANG,EXIT_W_HANG };
struct behave {
    enum behavior how;
    pthread_mutex_t lock;
    pthread_cond_t cond;
    int th1_entered;
    int th2_entered;
};

void hanger(void);

void *th1_main(void *);
void *th2_main(void *);

#define WR(x) (void)write(1,x,sizeof(x) - 1)

int main(int argc,char **argv) {
    int error;
    struct behave how;
    pthread_t th1,th2;

    error = pthread_mutex_init(&global_mtx,NULL);
    if (error)
        die(error,"pthread_mutex_init global_mtx");
    error = pthread_mutex_init(&how.lock,"pthread_mutex_init how.lock");
    error = pthread_cond_init(&how.cond,"pthread_cond_init how.cond");
    how.how = NORMAL;
    how.th1_entered = 0;
    how.th2_entered = 0;
    if (argc > 1) {
        if (strcmp(argv[1],"exit") == 0)
            how.how = EXIT_WO_HANG;
        else if (strcmp(argv[1],"hang") == 0)
            how.how = EXIT_W_HANG;
        else if (strcmp(argv[1],"normal") != 0)
            die(0,"usage: example [normal|exit|hang]");
    }
    atexit(hanger);
    error = pthread_create(&th1,NULL,th1_main,&how);
    if (error)
        die(error,"pthread_create th1");
    error = pthread_create(&th2,th2_main,"pthread_create th2");
    /* now wait for threads */
    error = pthread_join(th1,NULL);
    error = pthread_join(th2,NULL);
    printf("joined,normal exitn");
    return 0;
}

void *th1_main(void *arg) {
    struct behave *how = arg;

    WR("thread 1 startn");
    (void) pthread_mutex_lock(&global_mtx);
    (void) pthread_mutex_lock(&how->lock);
    how->th1_entered = 1;
    pthread_cond_signal(&how->cond);
    while (how->th2_entered == 0)
        (void) pthread_cond_wait(&how->cond,&how->lock);
    WR("thread 1 sees thread 2 startedn");
    (void) pthread_mutex_unlock(&how->lock);
    if (how->how == EXIT_W_HANG)
        WR("thread 1 not unlockingn");
    else
        (void) pthread_mutex_unlock(&global_mtx);
    return NULL;
}

void *th2_main(void *arg) {
    struct behave *how = arg;

    WR("thread 2 startn");
    (void) pthread_mutex_lock(&how->lock);
    how->th2_entered = 1;
    pthread_cond_signal(&how->cond);
    while (how->th1_entered == 0)
        (void) pthread_cond_wait(&how->cond,&how->lock);
    WR("thread 2 sees thread 1 startedn");
    (void) pthread_mutex_unlock(&how->lock);
    if (how->how != NORMAL) {
        WR("thread 2 exit()n");
        exit(1);
    }
    return NULL;
}

void hanger(void) {
    /* this is what will cause us to hang,in the one case */
    WR("hanger startn");
    pthread_mutex_lock(&global_mtx);
    WR("hanger got global mutexn");
    pthread_mutex_unlock(&global_mtx);
    WR("hanger finishn");
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读