Signal thread stop through a pipe; fixes issues where the statistics thread would...
[cubemap] / thread.cpp
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <signal.h>
6 #include <errno.h>
7
8 #include "thread.h"
9         
10 Thread::~Thread() {}
11
12 void Thread::run()
13 {
14         should_stop = false;
15         int pipefd[2];
16         if (pipe2(pipefd, O_CLOEXEC) == -1) {
17                 perror("pipe");
18                 exit(1);
19         }
20         stop_fd_read = pipefd[0];
21         stop_fd_write = pipefd[1];
22         pthread_create(&worker_thread, NULL, &Thread::do_work_thunk, this);
23 }
24
25 void Thread::stop()
26 {
27         should_stop = true;
28         char ch = 0;
29         int err;
30         do {
31                 err = write(stop_fd_write, &ch, 1);
32         } while (err == -1 && errno == EINTR);
33
34         if (err == -1) {
35                 perror("write");
36                 exit(1);
37         }
38
39         do {
40                 err = close(stop_fd_write);
41         } while (err == -1 && errno == EINTR);
42
43         if (err == -1) {
44                 perror("close");
45                 // Can continue (we have close-on-exec).
46         }
47
48         pthread_kill(worker_thread, SIGHUP);
49         if (pthread_join(worker_thread, NULL) == -1) {
50                 perror("pthread_join");
51                 exit(1);
52         }
53         
54         do {
55                 err = close(stop_fd_read);
56         } while (err == -1 && errno == EINTR);
57
58         if (err == -1) {
59                 perror("close");
60                 // Can continue (we have close-on-exec).
61         }
62 }
63
64 void *Thread::do_work_thunk(void *arg)
65 {
66         Thread *thread = reinterpret_cast<Thread *>(arg);
67         thread->do_work();
68         return NULL;
69 }
70