tijko
tijko

Reputation: 8292

tgkill kills entire process instead of just the tid passed

I have been trying to use tgkill to remotely kill a thread. I know that pthread_kill is recommended for this kind of thing because of there not being any glibc wrappers for tgkill but, I will be making the kill call outside of the process.

I've made a small example here to show what has been happening.

#define _GNU_SOURCE

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

#define GETTID 224


void helper1(void);
void helper2(void);

int main(int argc, char *argv[])
{
    pid_t process_id, thread_id;
    pthread_t h1, h2;

    process_id = getpid();
    thread_id = syscall(GETTID);

    printf("Main Thread: (PID-> %d :: TID-> %d\n", process_id, thread_id);

    pthread_create(&h1, NULL, (void *) helper1, NULL);
    sleep(1); // slight delay in creating each thread.
    pthread_create(&h2, NULL, (void *) helper2, NULL);

    printf("Entering Main's loop\n");

    for (;;) 
        ;

    return 0;
}

void helper1(void)
{
    pid_t process_id, thread_id;

    process_id = getpid();
    thread_id = syscall(GETTID);

    printf("Helper1 Thread: (PID-> %d :: TID-> %d\n", process_id, thread_id);

    sleep(3);

    printf("Entering Helper1's loop\n");

    for (;;)
        ;
}

void helper2(void)
{
    pid_t process_id, thread_id;

    process_id = getpid();
    thread_id = syscall(GETTID);

    printf("Helper2 Thread: (PID-> %d :: TID-> %d\n", process_id, thread_id);

    sleep(3);

    printf("Entering Helper2's loop\n");

    for (;;)
        ;
}

Compiling the following after getting and passing tgid and one of the thread id's that printed out.

#define _GNU_SOURCE

#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/syscall.h>

#define TGKILL 270


int main(int argc, char *argv[])
{
    long ret;
    int tgid, tid;

    tgid = atoi(argv[1]);
    tid = atoi(argv[2]);

    ret = syscall(TGKILL, tgid, tid, SIGTERM);

    if (ret != 0)
        perror("tgkill");

    return 0;
}

Calling the above passing both the tgid and tid ends with the entire process being killed instead of the expected outcome of just the tid being ended and the main process continuing to loop along.

Is this the correct outcome here and I'm just not understanding the use of tgkill or am I making some kind of error calling here?

Upvotes: 1

Views: 4594

Answers (1)

Kerrek SB
Kerrek SB

Reputation: 477000

From man pthread_kill (essentially a pthreads wrapper around the tgkill syscall):

Signal dispositions are process-wide: if a signal handler is installed, the handler will be invoked in the thread thread, but if the disposition of the signal is "stop", "continue", or "terminate", this action will affect the whole process.

The "terminate" signal is delivered to the designated thread, but the effect is to kill the entire process.

Upvotes: 4

Related Questions