Hi,
Unable to output messages in syslog function immediately after restarting the log daemon.
Caused by ECONNREFUSED on errno in the following __vsyslog function.
(libc/misc/syslog/syslog.c)
void
__vsyslog(int pri, const char *fmt, va_list ap)
{
.
.
.
retry:
if (LogFile >= 0) {
do {
/* can't just use write, it can result in SIGPIPE */
rc = send(LogFile, p, last_chr + 1 - p, MSG_NOSIGNAL);
if (rc < 0) {
switch (errno) {
case EINTR:
break;
case ECONNRESET:
/* syslogd restarted, reopen log */
closelog_intern(1);
openlog_intern();
goto retry;
case EAGAIN:
/* syslogd stalled, noting we can do */
default:
closelog_intern(1); /* 1: do not reset LogXXX globals to default */
goto write_err;
}
rc = 0;
}
p += rc;
} while (p <= last_chr);
goto getout;
}
.
.
.
You can check it with the following sample.
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/signal.h>
#include <sys/syslog.h>
static const struct sockaddr SyslogAddr = {
.sa_family = AF_UNIX,
.sa_data = "/dev/log"
};
static int LogFile;
static int OpenLogSocket(void);
int main(void)
{
char tbuf[1024];
char strbuf[1024];
time_t now;
int rc, count = 0;
printf("\nSyslog loop start!\n\n");
if (0 == OpenLogSocket() ) {
return 1;
}
while (fgets(strbuf, 1024, stdin)) {
if ((char)'e' == strbuf[0]) {
printf("Syslog loop end\n");
break;
}
(void)time(&now);
sprintf(tbuf, "<%d>%.15s Test %u", LOG_USER | LOG_NOTICE,
ctime(&now) + 4, count++);
retry:
rc = send(LogFile, tbuf, strlen(tbuf), MSG_NOSIGNAL);
if (rc < 0) {
switch (errno) {
case EINTR:
printf("Syslog send error EINTR\n");
break;
case ECONNRESET:
// case ECONNREFUSED:
close(LogFile);
if (0 == OpenLogSocket() ) {
return 1;
}
goto retry;
case EAGAIN:
printf("Syslog send error EAGAIN\n");
break;
default:
printf("Syslog send error default (%d)\n", errno);
break;
}
}
}
close(LogFile);
return 0;
}
int OpenLogSocket(void)
{
int FdFlag;
const struct timeval tv = { 1, 0 };
LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
if (-1 == LogFile) {
printf("Syslog open error\n");
return 0;
}
fcntl(LogFile, F_SETFD, FD_CLOEXEC);
FdFlag = fcntl(LogFile, F_GETFL);
fcntl(LogFile, F_SETFL, O_NONBLOCK | FdFlag);
if (-1 != connect(LogFile, &SyslogAddr, sizeof(SyslogAddr))) {
fcntl(LogFile, F_SETFL, ~O_NONBLOCK & fcntl(LogFile, F_GETFL));
setsockopt(LogFile, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
}
else {
printf("Syslog connect error\n");
close(LogFile);
return 0;
}
return 1;
}
When you run the sample, you can send the syslog by return input.
If the log daemon is restarted without exiting the sample, the syslog cannot be sent.
If you delete the comment (//) in the sample, you can send the syslog.
OS:OpenWrt Chaos Calmer 15.05.1 Linux-3.14.77 uClibc-ng-1.0.14
I think it needs to be at least ECONNREFUSED.
Thanks,
--
Takeru Fukushima
Show replies by date
Hi Takeru,
Takeru Fukushima wrote,
Hi,
Unable to output messages in syslog function immediately after restarting the log
daemon.
Caused by ECONNREFUSED on errno in the following __vsyslog function.
(libc/misc/syslog/syslog.c)
I am unable to reproduce it with following test case and busybox
syslogd. What kind of syslogd do you are using?
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/signal.h>
#include <sys/syslog.h>
int main(void)
{
char tbuf[1024];
char strbuf[1024];
time_t now;
int rc, count = 0;
printf("\nSyslog loop start!\n\n");
openlog("test", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
while (fgets(strbuf, 1024, stdin)) {
if ((char)'e' == strbuf[0]) {
printf("Syslog loop end\n");
break;
}
syslog(LOG_USER|LOG_NOTICE, "Test %u", count++);
}
closelog();
return 0;
}
On Wed, 27 Jan 2021 05:42:13 +0100
Waldemar Brodkorb <wbx(a)uclibc-ng.org> wrote:
Hi Takeru,
Takeru Fukushima wrote,
Hi,
Unable to output messages in syslog function immediately after restarting the log
daemon.
Caused by ECONNREFUSED on errno in the following __vsyslog function.
(libc/misc/syslog/syslog.c)
I am unable to reproduce it with following test case and busybox
syslogd. What kind of syslogd do you are using?
Hi Waldemar,
Thanks for the test case.
However, I was able to reproduce it using your test case.
I use logd in ubox-2015-11-22 Openwrt package.