summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorauric <auric7@protonmail.com>2026-02-22 18:18:36 -0600
committerauric <auric7@protonmail.com>2026-02-22 18:19:11 -0600
commitb2dd175b900556fb6d7bb2928cad53e9d73fc6a7 (patch)
tree5bdc716b569cc0ec2ad9b68efe2d68de2f0b4b93 /src
parent52f92ea70f74008d82d21fef5085fb7380314ea1 (diff)
Fix log tail rotation handling and SIGHUP cleanup
- Detect IN_MOVE_SELF/IN_DELETE_SELF events in log_tail_handle and re-open the watched path so srcds log rotation is followed correctly - Parse inotify events rather than blindly draining them - Call log_tail_cleanup() before log_tail_init() on SIGHUP to prevent fd leaks on reload Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'src')
-rw-r--r--src/log_tail.c45
-rw-r--r--src/main.c7
2 files changed, 46 insertions, 6 deletions
diff --git a/src/log_tail.c b/src/log_tail.c
index d352f8f..973cc0b 100644
--- a/src/log_tail.c
+++ b/src/log_tail.c
@@ -47,7 +47,8 @@ void log_tail_init(void) {
close(log_fd);
continue;
}
- int wd = inotify_add_watch(ifd, path, IN_MODIFY);
+ int wd = inotify_add_watch(ifd, path,
+ IN_MODIFY | IN_MOVE_SELF | IN_DELETE_SELF);
if (wd < 0) {
log_warn("log_tail: inotify_add_watch %s: %s",
path, strerror(errno));
@@ -95,9 +96,22 @@ static LogWatch *watch_for_inotify_fd(int fd) {
void log_tail_handle(int inotify_fd) {
LogWatch *w = watch_for_inotify_fd(inotify_fd);
if (!w) return;
+
+ /* Parse inotify events — detect log rotation (file moved or deleted) */
char evbuf[4096];
- while (read(inotify_fd, evbuf, sizeof(evbuf)) > 0)
- ;
+ int rotated = 0;
+ ssize_t nread;
+ while ((nread = read(inotify_fd, evbuf, sizeof(evbuf))) > 0) {
+ char *p = evbuf;
+ while (p < evbuf + nread) {
+ struct inotify_event *ie = (struct inotify_event *)p;
+ if (ie->mask & (IN_MOVE_SELF | IN_DELETE_SELF))
+ rotated = 1;
+ p += sizeof(struct inotify_event) + ie->len;
+ }
+ }
+
+ /* Drain any new data from the current log fd before re-opening */
char buf[RING_BUF_LINE_MAX];
ssize_t n;
while ((n = read(w->log_fd, buf, sizeof(buf) - 1)) > 0) {
@@ -105,6 +119,31 @@ void log_tail_handle(int inotify_fd) {
ring_push(w->unit->output, buf, (int)n);
client_broadcast_output(w->unit->name, buf, 0);
}
+
+ if (!rotated) return;
+
+ /* Log file was rotated — re-open the path to follow the new file */
+ inotify_rm_watch(w->inotify_fd, w->watch_wd);
+ close(w->log_fd);
+ w->log_fd = -1;
+
+ int log_fd = open(w->path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (log_fd < 0) {
+ log_warn("log_tail: cannot re-open %s after rotation: %s",
+ w->path, strerror(errno));
+ return;
+ }
+ int wd = inotify_add_watch(w->inotify_fd, w->path,
+ IN_MODIFY | IN_MOVE_SELF | IN_DELETE_SELF);
+ if (wd < 0) {
+ log_warn("log_tail: inotify_add_watch after rotation %s: %s",
+ w->path, strerror(errno));
+ close(log_fd);
+ return;
+ }
+ w->log_fd = log_fd;
+ w->watch_wd = wd;
+ log_info("log_tail: re-opened %s after rotation", w->path);
}
void log_tail_cleanup(void) {
diff --git a/src/main.c b/src/main.c
index f242489..901ce74 100644
--- a/src/main.c
+++ b/src/main.c
@@ -59,10 +59,11 @@ static void handle_signal(void) {
case SIGHUP:
log_info("SIGHUP received — reloading units");
+ log_tail_cleanup();
/* Reload unit descriptors. Existing runtime state is preserved. */
g.unit_count = 0;
unit_load_all();
- log_tail_init();
+ log_tail_init();
break;
}
}
@@ -206,8 +207,6 @@ int main(int argc, char *argv[]) {
ev.data.fd = g.signal_fd;
epoll_ctl(g.epoll_fd, EPOLL_CTL_ADD, g.signal_fd, &ev);
- log_tail_init();
-
/* Load unit descriptors */
if (unit_load_all() < 0) {
log_error("Failed to load units");
@@ -215,6 +214,8 @@ int main(int argc, char *argv[]) {
return 1;
}
+ log_tail_init();
+
/* Set up listening socket */
g.listen_fd = client_listen();
if (g.listen_fd < 0) {