Reputation: 11
I have a C/C++ program that runs as a systemd service using the default config for stdout and stderr, aka journald ( journalct -u SERVICE
. I want to see my printf calls with journald, and the only way I see them on a reasonable timeframe is if I use setvbuff(stdout, nullptr, 0, _IOLBF)
By reasonable I mean I haven't seen any output without either line buffering or no buffering. (_IOLBF
/ _IONBF
)
My question is really trying to understand if using setvbuff to modify the buffering is a reasonable thing to do. I see that line buffering is slower than fully buffered as demonstrated here stackOverflow post but without line buffering or no buffering, I am not getting any output from the program in journald. Printf works fine when running the binary, and when setting StandardOutput=tty
.
About the program: This is a rather large embedded linux program serving as the front end. There are three other services which are essentially the back end with the same issue. I want to be 100% sure this is a safe thing to do since this embedded program will be used in a highly regulated field and cannot afford a memory leak/ other memory issues and these printfs serve as debugging logs.
Service config file:
[Unit]
Description="UI service"
[Service]
ExecStart=/home/root/startBinary
Restart=always
[Install]
WantedBy=multi-user.target
Relevant system.conf lines (unedited from default):
#DefaultStandardOutput=journal
#DefaultStandardError=inherit
Sample journalctl -u SERVICE
output without modifying buffering:
Aug 09 08:29:54 computername systemd[1]: Starting SERVICE...
Sample journalctl -u SERVICE
with line buffering/no buffering:
Aug 09 08:32:20 computername systemd[1]: Starting SERVICE...
Aug 09 08:32:21 computername systemd[1]: Hello world from SERVICE printf
Without modifying the buffer method, I haven't seen my printf come through to journald.
I have tried using setvbuff(stdio, nullptr, 0, _IOLBF)
and get the results I want.
Upvotes: 0
Views: 73
Reputation: 58667
The stdout
and stderr
streams are line buffered when connected to interactive devices. In Unix-like systems, this means TTYs. Otherwise they are fully buffered.
This default behavior might not always be what you want for reasons of efficiency or timely delivery; it may be a useful feature to have a configuration option in your software to override the buffering.
In a Linux system based on Glibc, you don't have to program this yourself. Using a utility program called stdbuf
, you can control the buffering disposition of the standard streams in a process (that is launched by stdbuf
as a child). stdbuf
works very simply via certain environment variables, making it possible to easily imitate what it does.
Note that according to ISO C, you can only change the buffering configuration of a standard I/O stream if no I/O operation has taken place on it. (Implementations may allow it to be more dynamic, but the standard doesn't require it.) If your software supports a feature to tweak the buffering of stdout
or stderr
, it should be done very close to the program startup, before anything has had a chance to use those streams.
Upvotes: 0
Reputation: 16697
Technically it depends on how well your libc implements it (as I/O buffering is provided by libc), but is generally safe, as it's something that already happens by default for certain outputs (line-buffering is the default when stdout is a tty, and is always default for stderr if I remember correctly), and you're still using the same underlying mechanism either way – it only changes when output will be flushed, not something fundamental in the operation.
[This should not be taken as providing a 100% guarantee.]
Upvotes: 0