在信号处理程序中销毁pthread mutex/rwlock

在信号处理程序中销毁pthread mutex/rwlock,c,multithreading,pthreads,mutex,C,Multithreading,Pthreads,Mutex,如何在信号处理程序中正确销毁pthread互斥锁或rwlock?例如,在下面的代码中,我有一个主线程和另外3个线程。所有线程都使用互斥锁和锁在某个数组的无限循环中执行某些任务。因为主线程也在执行某些任务,所以退出程序的唯一方法是使用信号处理程序。但通过这种方式,我不能销毁我的互斥对象/rwlock对象,因为不能保证该对象被解锁。如果我尝试解锁它,当然其中一个线程会再次锁定它。当我试图再次启动我的程序时,打印结果会被破坏。那么我该如何解决这个问题呢?下面是我使用rwlocks的代码示例: #inc

如何在信号处理程序中正确销毁pthread互斥锁或rwlock?例如,在下面的代码中,我有一个主线程和另外3个线程。所有线程都使用互斥锁和锁在某个数组的无限循环中执行某些任务。因为主线程也在执行某些任务,所以退出程序的唯一方法是使用信号处理程序。但通过这种方式,我不能销毁我的互斥对象/rwlock对象,因为不能保证该对象被解锁。如果我尝试解锁它,当然其中一个线程会再次锁定它。当我试图再次启动我的程序时,打印结果会被破坏。那么我该如何解决这个问题呢?下面是我使用rwlocks的代码示例:

#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <signal.h>

#include <stdlib.h>

#include "thread_data.h"
#include "exchange_types.h"

pthread_rwlock_t rwlock;

unsigned int main_time   = 500000;
unsigned int shift_time  = 1000000;
unsigned int mirror_time = 2000000;
unsigned int count_time  = 4000000;

void signal_handler(int signo) {

    // Destroying locked lock or mutex is UB
    pthread_rwlock_destroy(&rwlock);
    exit(1);

}

void* shift_letter_case_async( void* array ) {

    while(1) {

        if( pthread_rwlock_rdlock(&rwlock) < 0 )
            handle_error("rdlock[shift]");

        carray_t* arr = (carray_t*) array;
        shift_letter_case( arr->array, arr->size );

        if( pthread_rwlock_unlock(&rwlock) < 0 )
            handle_error("unlock[shift]");

        usleep(shift_time);

    }

    return NULL;

}

void* mirror_array_async( void* array ) {

    while(1) {

        if( pthread_rwlock_rdlock(&rwlock) < 0 )
            handle_error("rdlock[mirror]");

        carray_t* arr = (carray_t*) array;
        mirror_array( arr->array, arr->size );

        if( pthread_rwlock_unlock(&rwlock) < 0 )
            handle_error("unlock[mirror]");

        usleep(mirror_time);

    }

    return NULL;

}

void* count_async( void* array ) {

    while(1) {

        if( pthread_rwlock_wrlock(&rwlock) < 0 )
            handle_error("wrlock[count]");

        carray_t* arr = (carray_t*) array;
        count_upper_letters( arr->array, arr->size );

        if( pthread_rwlock_unlock(&rwlock) < 0 )
            handle_error("unlock[count]");

        usleep(count_time);

    }

    return NULL;

}

int main( int argc, char** argv ) {

    /* Common data */
    char letters[ 'z' - 'a' + 1 ];
    size_t letter_len;
    carray_t transferer;
    /* pthread data */
    pthread_t threads[3];

    /* Initializing array */
    letter_len = sizeof(letters);
    for( int i = 0; i < letter_len; i++ )       
        letters[i] = 'a' + i;

    transferer.array = letters;
    transferer.size = letter_len;

    /* Initializing signal handlers */
    if ( signal(SIGINT, signal_handler) == SIG_ERR )
        handle_error("signal[SIGINT]");
    if ( signal(SIGTERM, signal_handler) == SIG_ERR )
        handle_error("signal[SIGTERM]");

    /* Initializing locks */
    if( pthread_rwlock_init(&rwlock, NULL) < 0 )
        handle_error("pthread_rwlock_init");

    /* Initializing threads */
    if( pthread_create( &threads[0], NULL, shift_letter_case_async, &transferer ) != 0 )
        handle_error("phtread_create[shift_letter_case]");

    if( pthread_create( &threads[1], NULL, mirror_array_async, &transferer ) != 0 )
        handle_error("phtread_create[mirror_array]");

    if( pthread_create( &threads[2], NULL, count_async, &transferer ) != 0 )
        handle_error("phtread_create[count]");

    while(1) {      

        if( pthread_rwlock_wrlock(&rwlock) < 0 )
            handle_error("wrlock[main]");

        print_array(letters, letter_len);

        if( pthread_rwlock_unlock(&rwlock) < 0 )
            handle_error("unlock[main]");

        usleep(main_time);


    }

    return 0;

}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“thread_data.h”
#包括“exchange_types.h”
pthread_rwlock_t rwlock;
无符号int main_时间=500000;
无符号整数移位时间=1000000;
无符号整数镜像时间=2000000;
无符号整数计数\u时间=4000000;
无效信号处理器(int signo){
//销毁锁定锁或互斥锁是不可能的
pthread_rwlock_destroy(&rwlock);
出口(1);
}
void*移位\字母\大小写\异步(void*数组){
而(1){
if(pthread\u rwlock\u rdlock(&rwlock)<0)
处理错误(“rdlock[shift]”;
carray_t*arr=(carray_t*)数组;
移位字母大小写(arr->array,arr->size);
if(pthread\u rwlock\u unlock(&rwlock)<0)
处理错误(“解锁[移位]”);
usleep(轮班时间);
}
返回NULL;
}
void*mirror\u array\u async(void*array){
而(1){
if(pthread\u rwlock\u rdlock(&rwlock)<0)
句柄错误(“rdlock[mirror]”;
carray_t*arr=(carray_t*)数组;
镜像数组(arr->array,arr->size);
if(pthread\u rwlock\u unlock(&rwlock)<0)
处理错误(“解锁[镜像]”);
usleep(镜像时间);
}
返回NULL;
}
void*count\u异步(void*array){
而(1){
if(pthread\u rwlock\u wrlock(&rwlock)<0)
句柄错误(“wrlock[count]”;
carray_t*arr=(carray_t*)数组;
计数上字母(arr->array,arr->size);
if(pthread\u rwlock\u unlock(&rwlock)<0)
处理错误(“解锁[计数]”);
usleep(计数时间);
}
返回NULL;
}
int main(int argc,字符**argv){
/*公共数据*/
字符字母['z'-'a'+1];
大小字母长度;
卡雷特转移者;
/*pthread数据*/
pthread_t线程[3];
/*初始化数组*/
letter_len=大小(字母);
对于(int i=0;i

>P>而不是你提出的非常危险的探听方法,考虑通过排列每个线程的信号来关闭,每个线程通过有序的关闭来响应。让主线程在这种情况下连接其他线程,以便它知道它们何时完成;然后,它可以干净地拆除任何持久同步结构、临时文件等


或者,只向主线程发送信号,并让它以正确同步的方式发出一个标志,使其他线程将其识别为要关闭的指令,然后按上述方式继续(加入工作线程,然后拆除)。

我认为我的第一个天真尝试是更改while(1)“running”定义为“running”的线程和main to while(running):

volatile int running = 1;
将信号处理器更改为:

void signal_handler(int signo) {
    running = 0;
}
在main中返回之前,可以正常地连接线程。我没有运行这个,所以我可能完全错了。此外,您可能希望usleep函数具有“if(running)”谓词