18

I have been searching for some time and haven't found a definitive answer yet. The only link I found till now which sheds some light on this is here.

Konoha
  • 337
  • 1
  • 4
  • 13

3 Answers3

17

According to the POSIX Specification syslog(), openlog() and closelog() are thread safe.

There's another thread that answers this question as well and it is dated as far back as 2009. Here's the link syslog_r for Linux?.

Community
  • 1
  • 1
alvits
  • 6,550
  • 1
  • 28
  • 28
  • on the page you've linked, `syslog()` etc aren't under "thread safety" section, but under "Thread cancellation". I'm not concurrency/posix expert, but this doesn't sound right. – Alexander Malakhov Mar 19 '14 at 05:42
  • @AlexanderMalakhov The section you are looking at says that ALL posix functions are thread safe, except the following ones. And syslog/etc. is not part of that list of non-threadsafe functions - therefore they are part of the thread-safe functions. – nos Apr 01 '15 at 08:24
  • @nos ah, right. At the moment of first comment I thought `shall be` means `should be`, but later I learned it's `must be`. I should mention, my initial doubts was from particular Android 4.2 implementation, where `syslog` leaked file descriptors when called from multiple threads. – Alexander Malakhov Apr 01 '15 at 08:37
5

(While I was working on this experiment, @user3088572 answered the question. Since I had this half-way complete, I'll post it anyway.)

The answer is "Yes", but this was determined purely by experimentation.

Source

Main process spawns three threads and waits while threads all print different strings at same time. Then after 1 second, it tells them all to stop and exits.

#include <pthread.h>
#include <syslog.h>

static int go = 1;

void * routine(void * str)
{
    int c = 0;
    while(go)
        syslog(7, "%d: %s", c++, (char *)str);
}

int main(int argc, char * argv[])
{
    pthread_t t1, t2, t3;
    char str1[100] = "111111111111111111111111111111111111111111111111111111111\n";
    char str2[100] = "222222222222222222222222222222222222222222222222222222222\n";
    char str3[100] = "333333333333333333333333333333333333333333333333333333333\n";

    openlog("syslog-test", LOG_PID, LOG_USER);

    pthread_create(&t1, NULL, &routine, str1);
    pthread_create(&t2, NULL, &routine, str2);
    pthread_create(&t3, NULL, &routine, str3);

    sleep(1);
    go = 0; // threads should stop now

    // wait for threads to exit
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);    

    closelog(); 

    return (0);
}

Results

First of all, there were no core dumps or segmentation faults. So that's good.

Also, when observing the system logs (see below), we can see that none of the messages have intermixed characters. Each line is either all 1's, 2's, or 3's.

$ tail /var/log/syslog
Dec 18 16:44:18 mach99 syslog-test[23347]: 68: 222222222222222222222222222222222222222222222222222222222
Dec 18 16:44:18 mach99 syslog-test[23347]: 69: 222222222222222222222222222222222222222222222222222222222
Dec 18 16:44:18 mach99 syslog-test[23347]: 70: 222222222222222222222222222222222222222222222222222222222
Dec 18 16:44:18 mach99 syslog-test[23347]: 51: 333333333333333333333333333333333333333333333333333333333
Dec 18 16:44:18 mach99 syslog-test[23347]: 49: 111111111111111111111111111111111111111111111111111111111
Dec 18 16:44:18 mach99 syslog-test[23347]: 71: 222222222222222222222222222222222222222222222222222222222
Dec 18 16:44:18 mach99 syslog-test[23347]: 52: 333333333333333333333333333333333333333333333333333333333
Dec 18 16:44:18 mach99 syslog-test[23347]: 53: 333333333333333333333333333333333333333333333333333333333
Dec 18 16:44:18 mach99 syslog-test[23347]: 50: 111111111111111111111111111111111111111111111111111111111
Dec 18 16:44:18 mach99 syslog-test[23347]: 72: 222222222222222222222222222222222222222222222222222222222
Dec 18 16:44:18 mach99 syslog-test[23347]: 54: 333333333333333333333333333333333333333333333333333333333
Dec 18 16:44:18 mach99 syslog-test[23347]: 51: 111111111111111111111111111111111111111111111111111111111
Dec 18 16:44:18 mach99 syslog-test[23347]: 73: 222222222222222222222222222222222222222222222222222222222
Dec 18 16:44:18 mach99 syslog-test[23347]: 52: 111111111111111111111111111111111111111111111111111111111
Dec 18 16:44:18 mach99 syslog-test[23347]: 53: 111111111111111111111111111111111111111111111111111111111
Dec 18 16:44:18 mach99 syslog-test[23347]: 74: 222222222222222222222222222222222222222222222222222222222
Dec 18 16:44:18 mach99 syslog-test[23347]: 55: 333333333333333333333333333333333333333333333333333333333
Dec 18 16:44:18 mach99 syslog-test[23347]: 54: 111111111111111111111111111111111111111111111111111111111
rkyser
  • 3,241
  • 1
  • 19
  • 28
  • 7
    Note that proving the absence of bugs by testing is quite hard, and usually impossible. – nos Dec 18 '13 at 21:56
  • It was more an experiment to see what would happen if we had multiple threads writing to the syslog at the same time. – rkyser Dec 18 '13 at 22:07
5

The GNU Libc documentation for syslog describes the methods as currently "MT-safe" which is POSIX-speak for "thread-safe".

The methods are described as "AS-Unsafe" (that is, unsafe for use from an asynchronous signal handler).

The doc also notes (as of April 2015) that these specifications are "preliminary" and not guaranteed to be true in all future versions. (I think this disclaimer applies to the broad idea of categorizing glibc API functions "safety" properties, and this is still a bit of work in progress. I doubt any of the syslog-specific methods would get any looser though.)

P.T.
  • 24,557
  • 7
  • 64
  • 95
  • Yes, but never take the glibc documentation for granted of as correct interpretation for the POSIX standard. Eg. glibc uses localtime for syslog, but musl uses gmtime and POSIX implicitly recommends gmtime over localtime. syslog() is not specified to depend on the environment and thereby is not allowed to call any function whose behavior is dependant on the environment. – rurban Jan 14 '19 at 16:38