Bug 8656

Summary: Flood of syslog() calls temporarily blocks process
Product: uClibc Reporter: Martin Lottermoser <mjl-s>
Component: OtherAssignee: unassigned
Status: NEW ---    
Severity: normal CC: uclibc-cvs
Priority: P5    
Version: 0.9.33.2   
Target Milestone: ---   
Hardware: All   
OS: Linux   
Host: Target:
Build:

Description Martin Lottermoser 2016-02-05 12:51:21 UTC
On an AMD-Elan-based system with Linux 2.6.32 and uClibc 0.9.33.2, a flood of syslog() calls in a real-time process led to the process freezing up for about two seconds.

This was caused by the following code in libc/misc/syslog/sylog.c, vsyslog():

 write_err:
	/*
	 * Output the message to the console; don't worry about blocking,
	 * if console blocks everything will.  Make sure the error reported
	 * is the one from the syslogd failure.
	 */
	/* should mode be O_WRONLY | O_NOCTTY? -- Uli */
	/* yes, but in Linux "/dev/console" never becomes ctty anyway -- vda */
	if ((LogStat & LOG_CONS) &&
	    (fd = open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY)) >= 0) {
		p = strchr(tbuf, '>') + 1;
		last_chr[0] = '\r';
		last_chr[1] = '\n';
		(void)write(fd, p, last_chr - p + 2);
		(void)close(fd);
	}

The system in question had a serial console, configured for 19.2 kb/s with 8N1. The kernel's internal buffer for that console has a size of UART_XMIT_SIZE, i.e., 4096 bytes. Transmitting 4096 bytes at 19.2 kb/s with 8N1 requires 2.1 seconds.

Adding O_NONBLOCK to the open() call above fixed the problem, i.e., the comment a few lines above that call seems unnecessarily optimistic.