I was under impression that signals are delivered to a process only when process is executing a syscall. Given the fact that memset or memmove are note executing any syscalls they will not be interrupted by a signal handler. Am i wrong?
Why isn't memset() async-signal-safe?
41–50 of 98 posts
Re: Why isn't memset() async-signal-safe?
#42Couple of things. First, I don't think that's true nowadays. The discussion points that this (not restoring DF on signal return) is a kernel bug and should be fixed: https://lkml.org/lkml/2008/3/5/531 Second, the kernel tries to avoid doing too much work in the signal return code. It tries hard do _avoid_ heavy XSAVE and just preserve only the needed registers. This is the job of sigreturn(2) syscall btw. http://man7…
I mean, kernel bug or no, if that's how it actually works, then it isn't actually safe to be handle signals while executing these functions. If people are still working to change the code and standards we hold the code to, then you can't push changes that rely on the new behavior without introducing some truly bizarre race conditions.
Re: Why isn't memset() async-signal-safe?
#43The post makes it a bit unclear, so for the record: there's no theoretical reason the direction flag should be a problem. Just like any other callee-saved register, the kernel needs to save it to the stack and restore it when returning from the signal handler; there's nothing about the direction flag that makes it harder to do so, even if a signal handler is interrupting another signal handler or whatnot. And before…
I'm confused too. On x86, EFLAGS (of which the direction flag is bit 10) is absolutely preserved across signal delivery. It's the spot where the comparison result bits go, so if the issue in the linked blog post was real, it would be impossible to deliver a signal across a test/jump pair, making basically all compiled code signal-unsafe. I don't know what historical architectures may have had a bug with this, but it'…
https://lkml.org/lkml/2008/3/5/207
is the first message.
Basically: ABI implementation bug in kernel. https://lkml.org/lkml/2008/3/5/231
GCC started actually relying on the ABI being correct in version 4.3, folks noticed bug.
Re: Why isn't memset() async-signal-safe?
#44Slightly terrifying is the optimizer may very well replace the following while(n--) *m++ = c; With a call to the built in memset()
Re: Why isn't memset() async-signal-safe?
#45When some code is interrupted and the signal or interrupt handler calls memmove, that memmove will set up the direction flag for itself correctly. Its entire execution is nested within the handler. If it is interrupted by a nested interrupt, that nested one will restore the flag.
Now if an implementation of the memset function happens not to care about that flag, so that it changes direction from call to call, that's not a signal or interrupt problem! The flag can have arbitrary value in on entry to memcpy in an ordinary situation not involving threads or signals.
The moral is: never use the looping primitives on Intel without setting up the direction flag, if you care about reproducibility.
It goes without saying that the flag is part of the machine state; any machine context saving mechanism (for async situations) is broken if it neglects that flag.
Re: Why isn't memset() async-signal-safe?
#46Any time anybody tells you that POSIX isn't terrible, the subject of this article is the sort of thing you need to bear in mind. (For a long time, I thought that literally the only thing that POSIX didn't fuck up is the way they don't have any analogue to MAXIMUM_WAIT_OBJECTS. But then, after I gained more experience with POSIX, I realised that even if I don't understand how, this too was probably also something they…
MAXIMUM_WAIT_OBJECTS is also terrible of course, but even apart from that Win32 is not bright, at all. The doc contains so little details (or worse is sometime even false) that the real doc when you start to ask serious questions is ReactOS, Wine, or even the NT/2000 source leaks, and then IDA. Compared to that, Posix is actually documented and implemented mostly correctly by tons of OSes. Its easy to ship an API with basically no spec (so nobody can tell you that there is a bug when they find one - actually even if there were some real specs about Win32 I think there is public no way to report bugs in there to MS!), and that does not have to be compatible with any other implementation...
Re: Why isn't memset() async-signal-safe?
#47Slightly terrifying is the optimizer may very well replace the following while(n--) *m++ = c; With a call to the built in memset()
Re: Why isn't memset() async-signal-safe?
#48Slightly terrifying is the optimizer may very well replace the following while(n--) *m++ = c; With a call to the built in memset()
I'm fairly inexperienced on this matter. Can you give a real life example where this would be a bad thing?
Re: Why isn't memset() async-signal-safe?
#49Couple of things. First, I don't think that's true nowadays. The discussion points that this (not restoring DF on signal return) is a kernel bug and should be fixed: https://lkml.org/lkml/2008/3/5/531 Second, the kernel tries to avoid doing too much work in the signal return code. It tries hard do _avoid_ heavy XSAVE and just preserve only the needed registers. This is the job of sigreturn(2) syscall btw. http://man7…
Re: Why isn't memset() async-signal-safe?
#50Seems like a good argument against an architecture having stateful flags that affect the execution of other instructions. Or, at least, against having such flags and not including them in the state saved and restored when switching contexts (including to signals).
Processors are inherently extremely stateful; this is an argument against having unix-style signals.