Zirias, I was thinking of configuration where messages are piped to syslog, like in case of apache:
ErrorLog "|/usr/bin/logger -p local6.err -t httpd"
But it's probably not changing the general concept anyway.
This probably just means apache is using a
pipe(2) to
write(2) to (maybe using
popen(3) to simplify the code, but that's just a detail), and you should always expect that such things might block or even fail. So, you're right, it doesn't change anything about the general concept: writing logs is non-essential, so, best practice is to ignore errors and design your service so it will never slow down the essential functionality.
edit: talking about a large and wide-spread project like apache, I'd assume they "got it right". But I wouldn't assume that for every service/daemon out there. Writing a good daemon isn't exactly easy, it's easy to write one that works fine until something "unexpected" (like, slow logging) happens. You need knowledge and experience to get it right. POSIX offering "async" semantics, except when it doesn't (like e.g. with
syslog(3)), isn't too helpful either, you have to get creative working around that (e.g. by implementing your own thread-pool). If you follow old tutorials for writing a daemon, you'll probably find a model that
fork(2)s a process for each and every client, and does blocking I/O exclusively. That's nice and simple, but not scalable (forking thousands of processes for a busy service isn't the greatest idea)
and suffers from this very problem: anything slow (like logging) would slow down servicing the client…
edit2: Avoiding to fork a process for every client doesn't necessarily mean to have a thread for every client. You could just go for an event-driven design (and, I'd recommend to do so). POSIX offers a simple mechanism for that with e.g.
pselect(2). Unfortunately, this doesn't scale to a huge number of clients either (the set of file descriptors monitored is, well, limited). If
that is a problem, you have to resort to non-portable solutions, like e.g.
kqueue(2) on FreeBSD, or
epoll(7) on Linux. There are libraries, like e.g.
libevent, offering a portable API for all these platform-specific solutions.