如何终止正在等待信号量操作的线程

use*_*745 5 c linux semaphore ipc pthreads

我正在编写一个使用 ipc 共享内存和信号量的程序。有一个主服务器进程创建共享内存和信号量。任意数量的客户端进程都可以连接到共享内存并在允许的情况下对其进行读写。信号量提供阻塞机制来控制读取和写入。一切正常,除了当我尝试终止客户端时。访问共享内存的信号量块位于线程中,并且在进程终止时我无法释放信号量块,以便线程正确退出。我该怎么办呢?这是针对 Linux 的。

具体来说,有1个shm和2个sem。第一个 sem 阻止写入,第二个 sem 阻止读取。当客户端有东西要写时,它会等待写入 sem 为 0,然后将其设置为 1,写入,然后将读取 sem 设置为 0,这会释放等待的服务器以读取客户端写入的内容。一旦读取,服务器将写入 sem 设置回 0,并且队列中的下一个客户端开始写入。它挂在一个 semop 调用上,该调用在读取 sem 为 0 时释放。这个 semop 调用位于一个线程中,我需要弄清楚如何在让主线程终止之前正确退出该线程。

这是我想做但不起作用的示例(睡眠假装是挂起的 semop 调用):

#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

void termination_handler (int signum) {
    printf( "Got Signal\n" );
}

void *threadfunc( void *parm ) {
    struct sigaction action;

    action.sa_handler = termination_handler;
    sigemptyset( &action.sa_mask );
    action.sa_flags = 0;

    sigaction( SIGUSR1, &action, NULL );

    printf("Thread executing\n");

    sleep( 100 ); // pretending to be the semaphore

    pthread_exit( NULL );
}

int main() {
    int       status;
    pthread_t threadid;
    int       thread_stat;

    status = pthread_create( &threadid, NULL, threadfunc, NULL );

    if ( status <  0) {
        perror("pthread_create failed");
        exit(1);
    }

    sleep( 5 );

    status = pthread_kill( threadid, SIGUSR1 );

    if ( status <  0 )
        perror("pthread_kill failed");

    status = pthread_join( threadid, (void *)&thread_stat );
    if ( status <  0 )
        perror("pthread_join failed");

    exit( 0 );
}
Run Code Online (Sandbox Code Playgroud)

Moi*_*lva 4

他说,这是针对Linux的。

如果你能准确地说出你是怎么做的,那将会很有用。我假设您在 sem_wait 或 sem_timedwait 中阻塞。如果你的线程阻塞在那里并且你想中断它,你可以使用pthread_kill。

pthread_kill(blocking_thread_id, SIGUSR1);
Run Code Online (Sandbox Code Playgroud)

当然,您需要设置适当的信号处理程序(man sigaction)来捕获 SIGUSR1,并且需要检查 sem_wait() 的返回码是否为 EINTR,在这种情况下,您可以做任何您想做的事情,知道您被中断了并且没有拿到锁。

如果您正在使用进程,您只需使用kill()而不是pthread_kill()来提供进程ID。(抱歉,最初我误读并认为你正在使用线程)