Live data from Hacker News

Why isn't memset() async-signal-safe?

boston.conman.org

31–40 of 98 posts

Re: Why isn't memset() async-signal-safe?

#31

Note that (a) the issue was with clearing the direction flag on signal handler entry, not saving it; and (b) it's since been fixed in the kernel to conform to the ABI (which GCC blindly trusted) [1]. And after reading that thread, I'm not as convinced as I was a few minutes ago that this was an obvious kernel issue. Yes, the kernel mismatched the published ABI, but callee-vs-caller save and setup is not always consis…

[deleted]

Re: Why isn't memset() async-signal-safe?

#32
post #10

The 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's not true of x86. If memset isn't signal-safe on modern x86 linux, it's surely not because of EFLAGS state management.

Re: Why isn't memset() async-signal-safe?

#33

Earlier quoted context omitted.

Oh wow. When did this change? I vaguely seem to remember that as recently as Windows 7 (or was it 8.0?) there was trouble with AVX2 or something, but I can't find the info anywhere at the moment.

An OS can still use xsave incorrectly, such as by hardcoding the expected size rather than detecting it at runtime, or by getting some aspect of the CPUID leaf 0xd enumeration wrong. I wouldn't find it surprising if an initial implementation got one of the details wrong, resulting in a bug that wouldn't manifest until the next time the xsave layout changed.

The CPU designers could have protected against this by randomly fluctuating the size of the xsave'd data.

Re: Why isn't memset() async-signal-safe?

#35
Any 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 got wrong.)

Re: Why isn't memset() async-signal-safe?

#36
post #8

Related: Unix signals are deemed "unfixable" by some: https://lwn.net/Articles/414618/

Unix signal are an OS try at giving user a portable abstraction for software interrupts (HW Int & trap). It confusingly employs much of the jargon (masking, priorities, bottom halves...)

http://stackoverflow.com/questions/13341870/signals-and-inte...

I have the intuition knowing the HW/ASM & the code but ignoring how POSIX works (I read stevens, but I am not having all my answers) that unices reimplement in SW what the HW does with wires.

Maybe this could be fixable at the HW level? (and maybe I guess requiring kernel privileges)?

Re: Why isn't memset() async-signal-safe?

#37

Tricky! Even writing your own memset would experience the same behavior, since the compiler will assume the direction flag is unset. I agree with colanderman; the kernel should be saving every register when the signal handler is entered.

if you do 68000 ASM INT/TRAP handling, it is better to let the interrupt/signal do the cleaning restoring.

But I won't restart a war that has ended the day x86 architecture won over 68K.

Re: Why isn't memset() async-signal-safe?

#38
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?

Re: Why isn't memset() async-signal-safe?

#39

Seems 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.

Re: Why isn't memset() async-signal-safe?

#40
post #27
post #24

Couple 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.

This comment suggests that #DF is rarely used anyway https://lkml.org/lkml/2008/3/6/50

> The conclusion is that DF=1 in x86_64 64-bit code is extremely rare

Post reply on HN