> Can I just call mmap instead of anything requiring userspace coordination beyond function scope if I need dynamic memory in a signal handler?
Yes, but if you're doing nontrivial work, you probably don't just want memory for yourself, you want to share some actual program state with the main process. See the other comment I posted.
In practice, making any raw system call is async-signal-sae. POSIX doesn't specify this because it doesn't specify what is a system call at all - it's purely a C-language, compile-time interface, and a unikernel that makes everything a library call, a Windows subsystem, etc. are all valid ways to implement it. But on a system where mmap is in fact a system call (and the libc wrapper does nothing interesting) it follows from first principles: there's no userspace resource that can be left in an inconsistent state.
> How easy is it to fuck up the signalfd thing and end up not responding to SIGINT in a timely manner, because I'm being silly and doing some blocking work in the signalfd loop for some reason? Does that happen to people at all?
I mean, this is basically the same question as "How easy is it for a system that's only accessible via an HTTP API to get stuck processing an event and not process a POST /quit". If you're worried about messing up your event loop and getting stuck, then yes, SIGINT interrupting your process is useful -- but also, you've already admitted you don't know what the state of your process is. So an orderly shutdown is difficult. Any work you could do to make it easier turns out to be work that makes your original non-blocking design get implemented correctly.
You should probably just leave SIGINT at its default disposition (terminate the process immediately, same as SIGKILL) and save state to disk periodically or something. Or, at best, implement a signal handler that does very little interaction with process state, maybe just writing a log message (but note that syslog isn't async-signal-safe!) and exiting.
Yes, but if you're doing nontrivial work, you probably don't just want memory for yourself, you want to share some actual program state with the main process. See the other comment I posted.
In practice, making any raw system call is async-signal-sae. POSIX doesn't specify this because it doesn't specify what is a system call at all - it's purely a C-language, compile-time interface, and a unikernel that makes everything a library call, a Windows subsystem, etc. are all valid ways to implement it. But on a system where mmap is in fact a system call (and the libc wrapper does nothing interesting) it follows from first principles: there's no userspace resource that can be left in an inconsistent state.
> How easy is it to fuck up the signalfd thing and end up not responding to SIGINT in a timely manner, because I'm being silly and doing some blocking work in the signalfd loop for some reason? Does that happen to people at all?
I mean, this is basically the same question as "How easy is it for a system that's only accessible via an HTTP API to get stuck processing an event and not process a POST /quit". If you're worried about messing up your event loop and getting stuck, then yes, SIGINT interrupting your process is useful -- but also, you've already admitted you don't know what the state of your process is. So an orderly shutdown is difficult. Any work you could do to make it easier turns out to be work that makes your original non-blocking design get implemented correctly.
You should probably just leave SIGINT at its default disposition (terminate the process immediately, same as SIGKILL) and save state to disk periodically or something. Or, at best, implement a signal handler that does very little interaction with process state, maybe just writing a log message (but note that syslog isn't async-signal-safe!) and exiting.