#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <sys/poll.h>
+#include <errno.h>
#include <vector>
#include "client.h"
}
sleep:
- int left_to_sleep = stats_interval;
- do {
- left_to_sleep = sleep(left_to_sleep);
- } while (left_to_sleep > 0 && !should_stop);
+ // Wait until the stop_fd pipe is closed, stats_interval timeout,
+ // or a spurious signal. (The latter will cause us to write stats
+ // too often, but that's okay.)
+ pollfd pfd;
+ pfd.fd = stop_fd_read;
+ pfd.events = POLLIN | POLLRDHUP;
+
+ int nfds = poll(&pfd, 1, stats_interval * 1000);
+ if (nfds == 0 || (nfds == -1 && errno == EINTR)) {
+ continue;
+ }
+ if (nfds == 1) {
+ // Should stop.
+ break;
+ }
+ if (nfds == -1) {
+ perror("poll");
+ usleep(100000);
+ continue;
+ }
}
}
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
#include <signal.h>
+#include <errno.h>
#include "thread.h"
void Thread::run()
{
should_stop = false;
+ int pipefd[2];
+ if (pipe2(pipefd, O_CLOEXEC) == -1) {
+ perror("pipe");
+ exit(1);
+ }
+ stop_fd_read = pipefd[0];
+ stop_fd_write = pipefd[1];
pthread_create(&worker_thread, NULL, &Thread::do_work_thunk, this);
}
void Thread::stop()
{
should_stop = true;
+ char ch = 0;
+ int err;
+ do {
+ err = write(stop_fd_write, &ch, 1);
+ } while (err == -1 && errno == EINTR);
+
+ if (err == -1) {
+ perror("write");
+ exit(1);
+ }
+
+ do {
+ err = close(stop_fd_write);
+ } while (err == -1 && errno == EINTR);
+
+ if (err == -1) {
+ perror("close");
+ // Can continue (we have close-on-exec).
+ }
+
pthread_kill(worker_thread, SIGHUP);
if (pthread_join(worker_thread, NULL) == -1) {
perror("pthread_join");
exit(1);
}
+
+ do {
+ err = close(stop_fd_read);
+ } while (err == -1 && errno == EINTR);
+
+ if (err == -1) {
+ perror("close");
+ // Can continue (we have close-on-exec).
+ }
}
void *Thread::do_work_thunk(void *arg)
volatile bool should_stop;
+ // A pipe that you can poll on if you want to see when should_stop
+ // has been set to true; stop() will write a single byte to the pipe
+ // and then close the other end.
+ int stop_fd_read;
+
private:
pthread_t worker_thread;
+ int stop_fd_write;
};
#endif // !defined(_THREAD_H)