Skip to content

Commit 510f589

Browse files
Fix threading bugs: recv pointer arithmetic, signal handler safety, dead macro
renderd.c slave_thread recv loop: apply the same fix as upstream commit fddb0a9 applied to mod_tile.c -- the loop was overwriting ret_size with each recv() return value instead of accumulating it, and using struct pointer arithmetic (resp + ret_size) instead of byte arithmetic ((char*)resp + ret_size), so partial reads wrote into the wrong memory location. Also handle EINTR and separate n==0 (EOF) from n<0 (error). renderd.c request_exit: remove g_logger/strerror calls from this signal handler. Both functions are non-async-signal-safe (they use mutexes and malloc internally). Only write(2) -- which is async-signal-safe -- is needed here. render_config.h: remove dead HASHIDX_SIZE 22123 definition in the #else branch of #ifdef METATILE. METATILE is defined unconditionally two lines above, so this branch is unreachable. The authoritative value 2213 lives in request_queue.h. The dead definition caused confusion about which value would be used if METATILE were ever undefined. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 62ee90c commit 510f589

2 files changed

Lines changed: 25 additions & 12 deletions

File tree

includes/render_config.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@
121121
#define QUEUE_MAX (1024)
122122
#define REQ_LIMIT (512)
123123
#define DIRTY_LIMIT (10000)
124-
#define HASHIDX_SIZE 22123
125124
#endif
126125

127126
// Penalty for client making an invalid request (in seconds)

src/renderd.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,11 @@ enum protoCmd rx_request(struct protocol *req, int fd)
170170

171171
void request_exit(void)
172172
{
173-
// Any write to the exit pipe will trigger a graceful exit
173+
// Any write to the exit pipe will trigger a graceful exit.
174+
// This function is called from a signal handler, so only async-signal-safe
175+
// functions (write(2)) may be used here — no g_logger, no strerror.
174176
char c = 0;
175-
176-
g_logger(G_LOG_LEVEL_INFO, "Sending exit request");
177-
178-
if (write(exit_pipe_fd, &c, sizeof(c)) < 0) {
179-
g_logger(G_LOG_LEVEL_ERROR, "Failed to write to the exit pipe: %s", strerror(errno));
180-
}
177+
(void)write(exit_pipe_fd, &c, sizeof(c));
181178
}
182179

183180
void process_loop(int listen_fd)
@@ -683,18 +680,35 @@ void *slave_thread(void * arg)
683680
retry = 10;
684681

685682
while ((ret_size < sizeof(struct protocol)) && (retry > 0)) {
686-
ret_size = recv(pfd, resp + ret_size, (sizeof(struct protocol)
687-
- ret_size), 0);
683+
ssize_t n = recv(pfd, (char *)resp + ret_size,
684+
sizeof(struct protocol) - ret_size, 0);
685+
686+
if (n < 0) {
687+
if (errno == EINTR) {
688+
continue;
689+
}
690+
691+
if (errno == EPIPE) {
692+
close(pfd);
693+
pfd = FD_INVALID;
694+
ret_size = 0;
695+
g_logger(G_LOG_LEVEL_ERROR, "Pipe to Renderd slave closed");
696+
break;
697+
}
698+
699+
retry--;
700+
continue;
701+
}
688702

689-
if ((errno == EPIPE) || ret_size == 0) {
703+
if (n == 0) {
690704
close(pfd);
691705
pfd = FD_INVALID;
692706
ret_size = 0;
693707
g_logger(G_LOG_LEVEL_ERROR, "Pipe to Renderd slave closed");
694708
break;
695709
}
696710

697-
retry--;
711+
ret_size += n;
698712
}
699713

700714
if (ret_size < sizeof(struct protocol)) {

0 commit comments

Comments
 (0)