Cancel threads task with signal
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -57,5 +57,6 @@ dkms.conf
|
||||
|
||||
# User specific
|
||||
/kernel-sign
|
||||
.vscode/
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/c
|
||||
|
||||
1
chp4_threads/cancel_threads_signal/.gitignore
vendored
Normal file
1
chp4_threads/cancel_threads_signal/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
cancel_threads
|
||||
18
chp4_threads/cancel_threads_signal/Makefile
Normal file
18
chp4_threads/cancel_threads_signal/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
CC=gcc
|
||||
CFLAGS=-o cancel_threads -Wall -lpthread -lc -D_GNU_SOURCE
|
||||
SRCS=main.c
|
||||
|
||||
.DEFAULT_GOAL := build
|
||||
|
||||
build:
|
||||
$(CC) $(CFLAGS) -fsanitize=address -static-libasan $(SRCS)
|
||||
|
||||
release:
|
||||
$(CC) $(CFLAGS) $(SRCS)
|
||||
|
||||
debug:
|
||||
$(CC) $(CFLAGS) -fsanitize=address -static-libasan -ggdb $(SRCS)
|
||||
gdb -q cancel_threads
|
||||
|
||||
clean:
|
||||
rm -f cancel_threads
|
||||
66
chp4_threads/cancel_threads_signal/main.c
Normal file
66
chp4_threads/cancel_threads_signal/main.c
Normal file
@@ -0,0 +1,66 @@
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define THREAD_COUNT 10
|
||||
|
||||
void *expensive_task(void *);
|
||||
void send_finish_signal(void *);
|
||||
void handler(int);
|
||||
|
||||
pthread_t main_thread;
|
||||
pthread_t threads[THREAD_COUNT];
|
||||
|
||||
int main(void) {
|
||||
main_thread = pthread_self();
|
||||
|
||||
// Register handler for SIGCHLD signal
|
||||
signal(SIGCHLD, handler);
|
||||
|
||||
pthread_attr_t attr;
|
||||
if (pthread_attr_init(&attr) != 0) {
|
||||
perror("Error");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int n[THREAD_COUNT];
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
n[i] = i;
|
||||
printf("Create thread number %d\n", i);
|
||||
pthread_create(&threads[i], &attr, expensive_task, (void *)&n[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
printf("Waiting thread number %d...\n", i);
|
||||
pthread_join(threads[i], NULL);
|
||||
printf("Thread %d joined\n", i);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void handler(int sig) {
|
||||
printf("Caught signal %d\n", sig);
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
pthread_cancel(threads[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void send_finish_signal(void *args) {
|
||||
int *id = (int *)args;
|
||||
printf("Thread %d send SIGCHLD signal\n", *id);
|
||||
pthread_kill(main_thread, SIGCHLD);
|
||||
printf("Thread %d cleanup handle is done\n", *id);
|
||||
}
|
||||
|
||||
void *expensive_task(void *args) {
|
||||
pthread_cleanup_push(send_finish_signal, args);
|
||||
const int tid = *((int *)args);
|
||||
printf("Thread %d are running...\n", tid);
|
||||
sleep(rand() % 31);
|
||||
printf("Thread %d terminated!!!\n", tid);
|
||||
pthread_cleanup_pop(1);
|
||||
pthread_exit(0);
|
||||
}
|
||||
Reference in New Issue
Block a user