# pthread_kill 實驗

## **Thread as Process**

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

### Code

```c
#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 在增長。

```plaintext
$ 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 就是用這種方式做的。](https://dev.mukyu.tw/pthread-cancel-and-destructor)

### Code

```c
#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 優先結束。

```plaintext
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](https://man7.org/linux/man-pages/man2/gettid.2.html)

[pthread\_kill(3) - Linux manual page](https://man7.org/linux/man-pages/man3/pthread_kill.3.html)
