I Need a List of Async-Signal-Safe Functions from Glibc

I need a list of Async-Signal-Safe Functions from glibc

Finally latest versions of man 7 signal-safety contain interested list: signal-safety.7.html

Is sysinfo() async. signal safe?

sysinfo is just thin system call wrapper and async-signal-safe:

00000000000feb00 <sysinfo@@GLIBC_2.2.5>:
feb00: mov $0x63,%eax
feb05: syscall
feb07: cmp $0xfffffffffffff001,%rax
feb0d: jae feb10 <sysinfo@@GLIBC_2.2.5+0x10>
feb0f: retq
feb10: mov 0xbf359(%rip),%rcx
feb17: neg %eax
feb19: mov %eax,%fs:(%rcx)
feb1c: or $0xffffffffffffffff,%rax
feb20: retq

But there is no vDSO acceleration for it, so it is going to be much slower than clock_gettime with either CLOCK_REALTIME or CLOCK_MONOTONIC on current systems.

Do functions which are not defined as async-safe, such as mmap(2), effect other async-safe functions called in signal handler?

Yes.

If your substitute open() calls a function that is not async-signal-safe, then it is not safe for a signal handler to call your function. That it has the same name and signature as a standard function that is async-signal-safe is irrelevant. That it calls the replaced function or other async-signal-safe functions is irrelevant. That the prospective signal handler's call to a function that is not async-signal-safe would not be a direct one is irrelevant.

In response to the question update: in the event that the function presented in the question is called as a signal handler, it has undefined behavior on account of its call to mmap(). The details of that UB cannot be predicted, at least not from the relevant standards. That's what "undefined" means. There is no reason whatever to suppose that the actual and apparent effects of the open() call would be somehow protected from interference. Nor the general signal-handling mechanism. Nor anything else in the program.

The further you get from the locus of the UB, the less likely is any noticeable effect, and the more likely the OS is to contain it, but UB is not something to mess with. In principle, it may manifest as any behavior or behaviors within the power of your computer to produce, such as wiping your disk, turning off your CPU fan, or mailing your password to hackers.

Is pthread_kill async signal safe on Linux?

Summarizing Craig Estey's answers here (thanks, dude!):

In all (recent enough) man pages pthread_kill is listed as async-signal-safe. There is a comment in glibc sources which claims it isn't safe in the presence of fork(), so if you feel paranoid you could use tgkill(getpid(), <thread-id>, <signal-id>).

So, yeah -- both pthread_kill and tgkill should be ok.

On my CentOS 7 man doesn't list any of them as safe, but it is likely due to the fact of it being too old.

Async signal safety of fork()

This is now listed as a bug by RedHat:

Bug 1422161 - glibc: fork is not async-signal-safe

...

+++ This bug was initially created as a clone of Bug #1422159 +++

POSIX requires that fork is async-signal-safe. Our current
implementation is not.

Print int from signal handler using write or async-safe functions

If you really insist on doing the printing from a signal handler, you basically have 2 options:

  1. Block the signal except in a dedicated thread you create for handling the signal. This special thread can simply perform for (;;) pause(); and since pause is async-signal-safe, the signal handler is allowed to use any functions it wants; it's not restricted to only async-signal-safe functions. On the other hand, it does have to access shared resources in a thread-safe way, since you're now dealing with threads.

  2. Write your own code for converting integers to decimal strings. It's just a simple loop of using %10 and /10 to peel off the last digit and storing them to a short array.

However, I would highly recommend getting this operation out of the signal handler, using the self-pipe trick or similar.

Is gettimeofday async signal safe ? and can it cause deadlock if used in signal handler?

gettimeofday is not defined as async-signal-safe, but if you pass 0 for the second (timezone) argument, it doesn't have to do anything that time and clock_gettime (both of which are officially async-signal-safe) don't also do, so as a matter of QoI it should be async-signal-safe in that case.

Your deadlock is inside the internal libc function __tz_convert.

#2  0x00007fc1b2d70d47 in __tz_convert () from /lib64/libc.so.6
#3 0x00000000004708f7 in Logger::getCurrentTimestamp(char*) ()

It appears to have been called directly from Logger::getCurrentTimestamp, but that's because it was "tail called" from a documented API function. There are only four functions in GNU libc that call __tz_convert (I grepped the source code): localtime, localtime_r, gmtime, and gmtime_r. Therefore, your problem is not that you are calling gettimeofday, but that you are calling one of those functions.

localtime and gmtime are obviously not async-signal-safe since they write to a global variable. localtime_r and gmtime_r are not async-signal-safe either, because they have to look at the global database of timezone information (yes, even gmtime_r does this — it might be possible to change it not to need to do that, but it still wouldn't be a thing you could rely on cross-platform).

I don't think there's a good workaround. Formatted output from an async signal handler is going to trip over all kinds of other problems; my advice is to restructure your code so that you never need to call logging functions from async signal handlers.



Related Topics



Leave a reply



Submit