Linux Signals – Internals
sklinuxblog.blogspot.com
sklinuxblog.blogspot.com
Someone correct me if I'm wrong, but because of the way the syscall callback operates, it could be interrupting threads at almost any stage. This makes executing the signal in a safe manner very difficult, and from the signal handler itself you can only run certain code. If i remember correctly, most signal handler implementations then get reduced to basically set some state and return, where the regular execution will then check for that state and react to it. Well, if your only going to process the signal during you main event loop anyways, then why not just exchange the information over a message queue, and send a message to the process when you want it to do something (ie reload configuration).
It sounds like a necessary use case to me. While most people would probably not use it, that doesn't invalidate its existence. Most people would probably not touch any low level code either way.
I find Win32 vastly superior than UNIX in this area.
User Process 99:
read socket Foo.
Kernel:
socket Foo has no data yet,
move 99 from the "running" list to the "sleeping" list.
run process 86
User Process 86:
do stuff
<< HARDWARE INTERRUPT!>>
Kernel:
Notice that 99 is waiting for this packet (via socket Foo).
Copy network data into 99's read buffer.
Move 99 back to the "running" list.
Run some processes, soon enough 99 gets a turn.
User process 99:
Oh good! I have data.
This sort of interface is usually much more useful for user applications than having the equivalent of their own ISR becuase it doesn't just send a notification -- it also controls the flow of the main application in a sane way. Simple, non-interactive applications can do this kind of blocking I/O all day long.More responsive applications need some kind of event loop. I.e. instead of blocking on an concrete I/O resource, they block notification service which tells them what I/O is available. In very different ways, Windows messages and Unix select()/poll() both do this.
The end result is usually a callback driven program. This is slightly similar to signals/ISRs (since signals are a kind of callback) -- but the game-changing difference is that the callbacks are only called when the application has voluntarily gone back to the event loop.
The application can integrate signals with its event loop with the self-pipe trick, or it can use Linux-specific APIs to have signals delivered over a file descriptor.
http://man7.org/linux/man-pages/man2/signalfd.2.html
I'm not saying signals are fun, but I don't think you've proposed anything different/better.
No, they don't. Just because signal handler code gets executed immediately, doesn't mean that the progam "receives" anything, as you cannot really touch anything that's also touched by the rest of the program, as you'd usually produce some form of race condition. The little that you can do safely usually is functionally equivalent to setting a flag for the rest of the program to process, which you can just as well achieve with any other "non-immediate" IPC mechanism, with much lower risk of getting it wrong.
> The application can integrate signals with its event loop with the self-pipe trick, or it can use Linux-specific APIs to have signals delivered over a file descriptor.
Which, for all itents and purposes, transforms them into yet another pipe/socket/event source, in wich case you might as well use one of the numerous other variants of those.
The self-pipe trick just shows that what most applications need is an event polling mechanism, not a preemptive callback. As for signalfd, I'd say that is exactly the kind of interface nemaar wants INSTEAD of traditional signals.
Sure handling them can be a pain in the ass, but I'd argue that signals are beautiful in their simplicity and extremely powerful. They are used for far more than signaling hang up and termination.
Unix did a lot of things right, but signals was certainly not one of them. Sometimes the simple ideas aren't the best ones.
> signals not being queueable
Are you sure? I'm not an expert on signal handling, but I believe these statements are not true in the case of signalfd(2), which allows you to read signals from a file descriptor and does not require a signal handler.
Also, signalfd(2) has its own lovely host of problems (caused by the fact that a file descriptor and signals don't match in abstractions). On fork(), sendmsg() or exec() or any other interesting event, the file descriptor starts to lean towards breaking POSIX. In addition, because of signals' interactions with threads, you get some even odder interactions when you read from the fd in a multithreaded program (they share the file descriptor table but will read different data).
real-time signals are queueable.
On the other hand, most programs aren't designed for context switching, so the design overhead of dealing with signals is significant. Furthermore, signals can arrive at any time, even during a syscall, and while it's possible to do reliable I/O in the face of random interruptions, it's quite tricky.
A standard mechanism needs to exist to send a message to an arbitrary process for things like "please gracefully terminate", but I think the ideal interface looks like a combination of 1) signalfd (minus some of the legacy signal-specific bits), for any signals the process can handle, and 2) an in-kernel mechanism to SIGKILL, SIGSTOP, or SIGCONT processes, which the process can't do anything about anyway.
(And things like SIGWINCH should never have been signals; those should just be a standard message associated with the terminal device itself.)
There's nothing beautiful when you have a MT program which also has to handle signals for various reasons. Signals are an abomination, not the least because a signal handler is global for the whole process.
There are so many hours in the day.
I am trying to read this book from cover to cover while I am in hospital. It is vastly more entertaining than the cable TV.
https://hn.algolia.com/?query=linux%20signals&sort=byPopular...