pthread_kill 實驗

·

2 min read

Thread as Process

在 Linux 底下,每個 thread 在排程時都會被當作 process,也都有個 pid。所以在 kill thread 的 pid 時,會在該 thread 起 signal handler。

Code

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

thread_local int cnt = 0;

void catch_function(int signo) {
    ++cnt;
    printf("%d cnt: %d\n", gettid(), cnt);
}

void* try_thread(void*) {
    printf("try_thread: %d\n", gettid());
    for (;;) {
        sleep(1);
    }
    return 0;
}

int main() {
    printf("main: %d\n", gettid());

    signal(SIGINT, catch_function);

    pthread_t t1;
    pthread_t t2;
    pthread_create(&t1, NULL, try_thread, NULL);
    pthread_create(&t2, NULL, try_thread, NULL);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    puts("joined");
    return 0;
}

Result

每個 thread (包括 main thread)都有自己的 cnt,所以送 signal 時,可以不同的 cnt 在增長。

$ g++ thread_kill.cpp -pthread
$ ./a.out &
[1] 1393371
main: 1393371
try_thread: 1393373
try_thread: 1393374
$ kill -s SIGINT 1393371 
1393371 cnt: 1
$ kill -s SIGINT 1393371 
1393371 cnt: 2
$ kill -s SIGINT 1393371 
1393371 cnt: 3
$ kill -s SIGINT 1393373
1393373 cnt: 1
$ kill -s SIGINT 1393373
1393373 cnt: 2
$ kill -s SIGINT 1393373
1393373 cnt: 3
$ kill -s SIGINT 1393374
1393374 cnt: 1
$ kill -s SIGINT 1393374
1393374 cnt: 2
$ kill -s SIGINT 1393374
1393374 cnt: 3

pthread_kill

在 process 裡面對自己的 thread 送 signal。pthread_cancel 就是用這種方式做的。

Code

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

void catch_function(int signo) {
    printf("%d signal: %d\n", gettid(), signo);
}

void* try_thread(void*) {
    printf("try_thread: %d\n", gettid());
    for (int i = 0; i < 3; ++i) {
        printf("%d: %d\n", gettid(), i);
        sleep(4);
    }
    return 0;
}

int main() {
    signal(SIGINT, catch_function);

    printf("main: %d\n", gettid());

    pthread_t t1;
    pthread_t t2;
    pthread_create(&t1, NULL, try_thread, NULL);
    pthread_create(&t2, NULL, try_thread, NULL);

    sleep(1);
    pthread_kill(t1, SIGINT);
    sleep(1);
    pthread_kill(t1, SIGINT);
    sleep(1);
    pthread_kill(t1, SIGINT);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    puts("joined");
    return 0;
}

Result

sleep 會因為 SIGINT 中斷,所以 kill 3 次 t1 會讓 t1 優先結束。

main: 1451041
try_thread: 1451042
1451042: 0
try_thread: 1451043
1451043: 0
1451042 signal: 2
1451042: 1
1451042 signal: 2
1451042: 2
1451042 signal: 2
1451043: 1
1451043: 2
joined

Reference

gettid(2) - Linux manual page

pthread_kill(3) - Linux manual page