tini icon indicating copy to clipboard operation
tini copied to clipboard

tini message are not flushed from stdout/stderr buffer until it die with the container

Open CyrilDevOps opened this issue 4 years ago • 8 comments

the Spawned child process ... and Main child existed appears at the end of our container logs because they aren't flushed from stdout buffer. after the fprintf \n, an fflush command need to be added to force the buffer to be flushed.

CyrilDevOps avatar Sep 30 '20 18:09 CyrilDevOps

Interesting. Those logs actually go to stderr, not stdout, and they have trailing newlines, so even if stderr were line-buffered, flushing shouldn't be necessary. Any chance you have something like stdbuf in the path to starting Tini that might be configuring the streams differently? https://linux.die.net/man/1/stdbuf

krallin avatar Nov 14 '20 12:11 krallin

sorry for the delay for this answer, we use tini with '-v' to get the spawn/exist status message.

with a dockerfile configured with tini v0.19.0 : ENTRYPOINT ["/tini", "-v", "--"] CMD ["/opt/ls.sh"]

ls.sh is just a dummy bash script : #!/bin/bash

ls

exit 123

When I build and run the docker image, I get : ls.sh [INFO tini (1)] Spawned child process '/opt/ls.sh' with pid '7' [INFO tini (1)] Main child exited normally (with status '123')

The INFO text show after the the 'ls.sh' result. We were expecting : [INFO tini (1)] Spawned child process '/opt/ls.sh' with pid '7' ls.sh [INFO tini (1)] Main child exited normally (with status '123')

CyrilDevOps avatar Feb 13 '21 00:02 CyrilDevOps

It's likely not tini's fault; stdout/stderr ordering is hard. Like this issue in Docker itself: ~https://github.com/moby/moby/issues/26986~ https://github.com/moby/moby/issues/31706

yosifkit avatar Feb 13 '21 00:02 yosifkit

Thanks. docker and logs ordering doesn't seems to be a 'new' problem. You can close this issue, I don't think there is any 'trick' tini can do.

CyrilDevOps avatar Feb 13 '21 02:02 CyrilDevOps

To set stdout and stderr as unbuffered, call setbuf(stdout, NULL) and setbuf(stderr, NULL). https://man7.org/linux/man-pages/man3/setbuf.3.html

pt9999 avatar Oct 31 '22 01:10 pt9999

@krallin Hi Thomas! You think it would be possible to switch stdout to line buffering?

By default the stdout buffer in libc is around 4k whereas stderr is unbuffered by default. By the time I have tini "child segmentation fault" log output in the docker log, my main app (child process) already restarted and printed a ton of logging. Would be nice to see child segmentation fault log line right when it happened aligned with the log output of the main process and its error messages (tini prints "child exits with signal" to stdout - info/debug logging not stderr - which is fine, not all exits with a signal are abnormal - sigterm due to docker restart). Switching stdout to linebuffering won't hurt performance since tini barely does any logging even with -vv

setlinebuf(stdout); the first line in main()

igor-borovkov avatar Jan 06 '23 21:01 igor-borovkov

@krallin As @igor-borovkov mentioned (thanks for digging out that info!), adding setlinebuf(stdout); at the beginning of main() fixes this.

Should I open a PR?

Out of curiosity, I did a bit of digging on my own, and found this interesting article about buffering, stating:

GNU libc (glibc) uses the following rules for buffering:

Stream Type Behavior
stdin input line-buffered
stdout (TTY) output line-buffered
stdout (not a TTY) output fully-buffered
stderr output unbuffered

So stderr is unbuffered by default, but stdout (which INFO, DEBUG and TRACE use) is only line-buffered if it's a TTY - and indeed, it works fine when running a container image using tini as PID 1 with docker run --tty ..., but that's not the common case. In the common case, when stdout is not a TTY, it is fully buffered.

Also, reading the glibc buffering docs, it looks like setlinebuf() is deprecated, and setvbuf() should be used instead, something like:

setvbuf(stdout, NULL, _IOLBF, BUFSIZ);

lbogdan avatar Feb 05 '24 23:02 lbogdan

Hello, maybe slightly unrelated but I wrote a blog post about different buffering approaches, in case you might find it interesting: https://blog.orhun.dev/stdout-vs-stderr/

orhun avatar Feb 06 '24 08:02 orhun