summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-11-05 19:00:31 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-11-05 19:00:31 +0100
commit3e926ca209e9ed7946d8287e579bdaff05f3c2b3 (patch)
tree96cca578db119f31a7aa46a45ebd21060e21039f /src
parent3af4bf15995be50deaef7ced0d0e0fdc2fc35ba5 (diff)
Use poll instead of a condition variable to time the sleepers
Diffstat (limited to 'src')
-rw-r--r--src/ot_clean.c43
1 files changed, 21 insertions, 22 deletions
diff --git a/src/ot_clean.c b/src/ot_clean.c
index 2ebfd42..dfac011 100644
--- a/src/ot_clean.c
+++ b/src/ot_clean.c
@@ -2,8 +2,9 @@
2 It is considered beerware. Prost. Skol. Cheers or whatever. */ 2 It is considered beerware. Prost. Skol. Cheers or whatever. */
3 3
4/* System */ 4/* System */
5#include <errno.h> 5#include <poll.h>
6#include <pthread.h> 6#include <pthread.h>
7#include <stdio.h>
7#include <string.h> 8#include <string.h>
8#include <unistd.h> 9#include <unistd.h>
9 10
@@ -102,27 +103,18 @@ int clean_single_torrent(ot_torrent *torrent) {
102 return clean_single_peer_list(torrent->peer_list6, OT_PEER_SIZE6) * clean_single_peer_list(torrent->peer_list4, OT_PEER_SIZE4); 103 return clean_single_peer_list(torrent->peer_list6, OT_PEER_SIZE6) * clean_single_peer_list(torrent->peer_list4, OT_PEER_SIZE4);
103} 104}
104 105
105static pthread_mutex_t g_clean_mutex = PTHREAD_MUTEX_INITIALIZER; 106/* Written to once, by clean_deinit, and never read: the byte stays in and
106static pthread_cond_t g_clean_wakeup = PTHREAD_COND_INITIALIZER; 107 every sleep after it returns at once */
108static int g_clean_pipe[2] = {-1, -1};
107 109
108static void clean_sleep(void) { 110static void clean_sleep(void) {
109 struct timespec deadline; 111 struct pollfd pfd;
110 112
111 clock_gettime(CLOCK_REALTIME, &deadline); 113 pfd.fd = g_clean_pipe[0];
112 deadline.tv_sec += OT_CLEAN_SLEEP / 1000000; 114 pfd.events = POLLIN;
113 deadline.tv_nsec += (OT_CLEAN_SLEEP % 1000000) * 1000; 115 pfd.revents = 0;
114 if (deadline.tv_nsec >= 1000000000) {
115 ++deadline.tv_sec;
116 deadline.tv_nsec -= 1000000000;
117 }
118 116
119 /* Both sides hold the mutex, so the flag cannot be cleared and signalled 117 poll(&pfd, 1, OT_CLEAN_SLEEP / 1000);
120 in the window between testing it and waiting on it */
121 pthread_mutex_lock(&g_clean_mutex);
122 while (g_opentracker_running)
123 if (pthread_cond_timedwait(&g_clean_wakeup, &g_clean_mutex, &deadline) == ETIMEDOUT)
124 break;
125 pthread_mutex_unlock(&g_clean_mutex);
126} 118}
127 119
128/* Clean up all peers in one bucket, remove timedout pools and torrents */ 120/* Clean up all peers in one bucket, remove timedout pools and torrents */
@@ -166,11 +158,18 @@ static void *clean_worker(void *args) {
166} 158}
167 159
168static pthread_t thread_id; 160static pthread_t thread_id;
169void clean_init(void) { pthread_create(&thread_id, NULL, clean_worker, NULL); } 161void clean_init(void) {
162 if (pipe(g_clean_pipe) == -1)
163 fprintf(stderr, "Warning: the cleaner has no pipe to be woken through and will take up to one sleep interval to stop.\n");
164 pthread_create(&thread_id, NULL, clean_worker, NULL);
165}
170 166
171void clean_deinit(void) { 167void clean_deinit(void) {
172 pthread_mutex_lock(&g_clean_mutex); 168 const char byte = 0;
173 pthread_cond_signal(&g_clean_wakeup); 169
174 pthread_mutex_unlock(&g_clean_mutex); 170 (void)!write(g_clean_pipe[1], &byte, 1);
175 pthread_join(thread_id, NULL); 171 pthread_join(thread_id, NULL);
172
173 close(g_clean_pipe[0]);
174 close(g_clean_pipe[1]);
176} 175}