1. 信號處理函數為多個線程共享。
2. 線程的私有信號在該線程被調度的時候傳遞(信號處理函數被處理)
pthread_kill()本質上調用tkill(), tgkill().
兩個例子說明上述情況:
1. 信號處理函數為多個線程共享。
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
class Prep_Test {
public:
Prep_Test() {
cancel_flag = 0;
id = 0;
};
static void* prepWrapper(void* args);
int cancel_flag;
pthread_t id;
};
class State_Test {
public:
State_Test() {
cancel_flag = 0;
id = 0;
};
static void* stateWrapper(void* args);
int cancel_flag;
pthread_t id;
};
class SIG_HANDLER {
public:
SIG_HANDLER() {
prepID[0] = 0;
prepID[1] = 0;
prepID[2] = 0;
stateID = 0;
};
Prep_Test prepTest[3];
State_Test stateTest;
pthread_t prepID[3];
pthread_t stateID;
};
SIG_HANDLER sigHandler;
void sighandler(int signo) {
pthread_t id = pthread_self();
printf("sighandler state thread id = %lu\n", id);
sigHandler.stateTest.cancel_flag = true;
}
void sighandler2(int signo) {
pthread_t id = pthread_self();
printf("sighandler prep thread id = %lu\n", id);
if (signo = SIGTERM) {
for (int i = 0; i < 3; i++) {
if (id == sigHandler.prepID[i]) {
sigHandler.prepTest[i].cancel_flag = true;
}
}
}
}
void * Prep_Test::prepWrapper(void* args) {
int rc;
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGTERM);
Prep_Test * p = (Prep_Test *)args;
if (p == NULL) return NULL;
struct sigaction actions;
memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask);
actions.sa_flags = 0;
actions.sa_handler = sighandler2;
rc = sigaction(SIGTERM, &actions, NULL);
printf("install prep sig action rc = %d\n", rc);
while(!(p->cancel_flag)) {
printf("prep thread %lu before sleep\n", pthread_self());
int rc = 0;//sleep(5);
printf("prep thread %lu after sleep %d\n", pthread_self(), rc);
}
printf("prep thread %lu exit\n", pthread_self());
p->cancel_flag = false;
return NULL;
}
void * State_Test::stateWrapper(void* args) {
int rc;
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGTERM);
State_Test * p = (State_Test *)args;
if (p == NULL) return NULL;
struct sigaction actions;
memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask);
actions.sa_flags = 0;
actions.sa_handler = sighandler;
rc = sigaction(SIGTERM, &actions, NULL);
printf("install state sig action rc = %d\n", rc);
while(!(p->cancel_flag)) {
printf("state thread %lu before sleep\n", pthread_self());
int rc = 0;//sleep(5);
printf("state thread %lu after sleep %d\n", pthread_self(), rc);
}
printf("state thread %lu exit\n", pthread_self());
p->cancel_flag = false;
return NULL;
}
int main() {
int rc;
rc = pthread_create(&(sigHandler.stateID), NULL, State_Test::stateWrapper, &(sigHandler.stateTest));
printf("create state thread rc = %d, id = %lu\n", rc, sigHandler.stateID);
rc = pthread_create(&(sigHandler.prepID[0]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[0]));
printf("create prep 0 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[0]);
rc = pthread_create(&(sigHandler.prepID[1]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[1]));
printf("create prep 1 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[1]);
rc = pthread_create(&(sigHandler.prepID[2]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[2]));
printf("create prep 2 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[2]);
sleep(3);
printf("___________________________\n");
printf("cancel state id = %lu\n", sigHandler.stateID);
pthread_kill(sigHandler.stateID, SIGTERM);
printf("brfore main sleep\n");
sleep(2);
printf("after main sleep\n");
return 0;
}
在運行之後, state線程的信號處理函數變成了prep線程的信號處理函數, 可見被替換, 只有一個信號處理函數。
2. 線程的私有信號在該線程被調度的時候傳遞(信號處理函數被處理)
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
class Prep_Test {
public:
Prep_Test() {
cancel_flag = 0;
id = 0;
};
static void* prepWrapper(void* args);
int cancel_flag;
pthread_t id;
};
void * Prep_Test::prepWrapper(void* args) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGTERM);
Prep_Test * p = (Prep_Test *)args;
if (p == NULL) return NULL;
while(!(p->cancel_flag)) {
printf("prep thread %lu before sleep\n", pthread_self());
int rc = 0;//sleep(5);
printf("prep thread %lu after sleep %d\n", pthread_self(), rc);
}
printf("prep thread %lu exit\n", pthread_self());
p->cancel_flag = false;
return NULL;
}
class State_Test {
public:
State_Test() {
cancel_flag = 0;
id = 0;
};
static void* stateWrapper(void* args);
int cancel_flag;
pthread_t id;
};
void * State_Test::stateWrapper(void* args) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGTERM);
State_Test * p = (State_Test *)args;
if (p == NULL) return NULL;
while(!(p->cancel_flag)) {
printf("state thread %lu before sleep\n", pthread_self());
int rc = 0;//sleep(5);
printf("state thread %lu after sleep %d\n", pthread_self(), rc);
}
printf("state thread %lu exit\n", pthread_self());
p->cancel_flag = false;
return NULL;
}
class SIG_HANDLER {
public:
SIG_HANDLER() {
prepID[0] = 0;
prepID[1] = 0;
prepID[2] = 0;
stateID = 0;
};
//static void sighandler(int signo);
Prep_Test prepTest[3];
State_Test stateTest;
pthread_t prepID[3];
pthread_t stateID;
};
SIG_HANDLER sigHandler;
void sighandler(int signo) {
pthread_t id = pthread_self();
printf("sighandler thread id = %lu\n", id);
if (signo = SIGTERM) {
if (id == sigHandler.stateID) {
sigHandler.stateTest.cancel_flag = true;
}
else {
for (int i = 0; i < 3; i++) {
if (id == sigHandler.prepID[i]) {
sigHandler.prepTest[i].cancel_flag = true;
}
}
}
}
}
int main() {
//Prep_Test prepTest[3];
//State_Test stateTest;
//pthread_t prepID[3];
//pthread_t stateID;
int rc;
//SIG_HANDLER sigHandler;
struct sigaction actions;
memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask);
actions.sa_flags = 0;
actions.sa_handler = sighandler;
rc = sigaction(SIGTERM, &actions, NULL);
printf("install sig action rc = %d\n", rc);
rc = pthread_create(&(sigHandler.stateID), NULL, State_Test::stateWrapper, &(sigHandler.stateTest));
printf("create state thread rc = %d, id = %lu\n", rc, sigHandler.stateID);
rc = pthread_create(&(sigHandler.prepID[0]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[0]));
printf("create prep 0 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[0]);
rc = pthread_create(&(sigHandler.prepID[1]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[1]));
printf("create prep 1 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[1]);
rc = pthread_create(&(sigHandler.prepID[2]), NULL, Prep_Test::prepWrapper, &(sigHandler.prepTest[2]));
printf("create prep 2 thread rc = %d, id = %lu\n", rc, sigHandler.prepID[2]);
sleep(3);
printf("___________________________\n");
printf("cancel state id = %lu\n", sigHandler.stateID);
pthread_kill(sigHandler.stateID, SIGTERM);
/*
printf("cancel prep0 id = %lu\n", sigHandler.prepID[0]);
pthread_kill(sigHandler.prepID[0], SIGTERM);
printf("cancel prep1 id = %lu\n", sigHandler.prepID[1]);
pthread_kill(sigHandler.prepID[1], SIGTERM);
printf("cancel prep2 id = %lu\n", sigHandler.prepID[2]);
pthread_kill(sigHandler.prepID[2], SIGTERM);
*/
printf("brfore main sleep\n");
sleep(2);
printf("after main sleep\n");
return 0;
}
經多次測試, 沒有發現這個信號被其它線程相應的情況。