Skip to content

Commit d9a0c2d

Browse files
committed
Switch from PTY to pipe for service log redirection
The PTY approach caused isatty() to return true for services using the log directive, triggering programs like fprintd (using glib) to emit ANSI escape codes and other TTY-specific formatting in syslog. Using a standard pipe ensures isatty() correctly returns false, so programs produce plain text output suitable for logging. For services that require line-buffered output, users can wrap the command with `stdbuf -oL` as documented in doc/config/logging.md. Fixes #455 Signed-off-by: Joachim Wiberg <[email protected]>
1 parent 178301b commit d9a0c2d

File tree

2 files changed

+37
-22
lines changed

2 files changed

+37
-22
lines changed

doc/config/logging.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,25 @@ Log rotation is controlled using the global `log` setting.
3939
**Example:**
4040

4141
service log:prio:user.warn,tag:ntpd /sbin/ntpd pool.ntp.org -- NTP daemon
42+
43+
Output Buffering
44+
----------------
45+
46+
When using the `log` directive, Finit redirects the service's stdout and
47+
stderr to a pipe connected to a logger process. Programs detect this as
48+
non-interactive output (i.e., `isatty()` returns false) and typically
49+
switch from line-buffered to fully-buffered mode.
50+
51+
Most well-behaved daemons explicitly flush their output or use syslog
52+
directly, so this is rarely an issue. However, if a service's log
53+
messages appear delayed or batched, you can force line-buffered output
54+
by wrapping the command with `stdbuf`:
55+
56+
service log /usr/bin/stdbuf -oL /path/to/command -- My service
57+
58+
The `-oL` option forces line-buffered output, and `-o0` forces unbuffered
59+
output. See `stdbuf(1)` for details.
60+
61+
> [!NOTE]
62+
> Using `stdbuf` is rarely necessary. Only use it if you observe actual
63+
> buffering issues with a specific service.

src/service.c

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -274,25 +274,22 @@ static int lredirect(svc_t *svc)
274274
{
275275
static int have_sysklogd = -1;
276276
pid_t svc_pid = getpid();
277+
int pipefd[2];
277278
pid_t pid;
278279
int fd;
279280

280281
/*
281-
* Open PTY to connect to logger. A pty isn't buffered
282-
* like a pipe, and it eats newlines so they aren't logged
282+
* Use a pipe to connect to logger. This ensures isatty()
283+
* returns false for the service, preventing programs from
284+
* emitting ANSI escape codes and other TTY-specific output.
283285
*/
284-
fd = posix_openpt(O_RDWR);
285-
if (fd == -1) {
286-
dbg("Failed posix_openpt(), errno %d: %s", errno, strerror(errno));
287-
svc->log.enabled = 0;
288-
return -1;
289-
}
290-
if (grantpt(fd) == -1 || unlockpt(fd) == -1) {
291-
dbg("Failed grantpt()|unlockpt(), errno %d: %s", errno, strerror(errno));
292-
close(fd);
286+
if (pipe(pipefd) == -1) {
287+
dbg("Failed pipe(), errno %d: %s", errno, strerror(errno));
293288
svc->log.enabled = 0;
289+
294290
return -1;
295291
}
292+
fd = pipefd[1]; /* Write end for service */
296293

297294
/*
298295
* First time, check if we have sysklogd logger tool.
@@ -322,17 +319,12 @@ static int lredirect(svc_t *svc)
322319
char *prio = "daemon.info";
323320
char buf[MAX_IDENT_LEN];
324321
char *tag;
325-
int fds;
326322

327323
sched_yield();
328324

329-
fds = open(ptsname(fd), O_RDONLY);
330-
close(fd);
331-
if (fds == -1) {
332-
logit(LOG_WARNING, "failed open() ptsname(%d), errno %d", fd, errno);
333-
_exit(0);
334-
}
335-
dup2(fds, STDIN_FILENO);
325+
close(pipefd[1]); /* Close write end in logger */
326+
dup2(pipefd[0], STDIN_FILENO);
327+
close(pipefd[0]);
336328

337329
/* Reset signals */
338330
sig_unblock();
@@ -388,10 +380,11 @@ static int lredirect(svc_t *svc)
388380
_exit(1);
389381
}
390382

391-
dup2(fd, STDOUT_FILENO);
392-
dup2(fd, STDERR_FILENO);
383+
close(pipefd[0]); /* Close read end in service */
384+
dup2(pipefd[1], STDOUT_FILENO);
385+
dup2(pipefd[1], STDERR_FILENO);
393386

394-
return close(fd);
387+
return close(pipefd[1]);
395388
}
396389

397390
/*

0 commit comments

Comments
 (0)