Live data from Hacker News

How Not to Write a Signal Handler

741mhz.com

31–40 of 52 posts

Re: How Not to Write a Signal Handler

#31

I've always found it interesting that the list of safe functions includes read(), write(), and most of the filesystem operations; so while printf is not safe, you could use write() if you really wanted to output.

write() is an OS system call, while printf() is a C function call.

C libraries can (and do) choose to buffer printf, while read/write are usually unbuffered.

Of course, both are mechanisms are modifying some global state (your terminal's state), and cannot be relied to be free of race-conditions.

Re: How Not to Write a Signal Handler

#32

Earlier quoted context omitted.

If the signal is received more than once it means it is more important :p "Oh shit!" "^C^C^C^C^C^C~C^C"

In my experience it usual means that you need some form of time reversal e.g. unsend an email or put a BEGIN TRAN before the SQL you just executed. Reasonably sure that can't be done in C even with all that undefined behaviour. However, if your IO monad implementation is sufficiently slow, you could ^C between when you thought the code had executed and when it actually bothered to get around to it. I can't believe th…

> I can't believe that none of the functional ninjas thought to add time travel as a benefit. Most remiss...

Ahem: https://hackage.haskell.org/package/tardis

Re: How Not to Write a Signal Handler

#33

Earlier quoted context omitted.

It's just that new programs often have more bugs in them, and bugs can sometimes end opening up an exploit vector.

> It's just that new programs often have more bugs in them... That sure is a broad brush that you are using.

I dunno. In general that's true.

Re: How Not to Write a Signal Handler

#34
post #32

Earlier quoted context omitted.

In my experience it usual means that you need some form of time reversal e.g. unsend an email or put a BEGIN TRAN before the SQL you just executed. Reasonably sure that can't be done in C even with all that undefined behaviour. However, if your IO monad implementation is sufficiently slow, you could ^C between when you thought the code had executed and when it actually bothered to get around to it. I can't believe th…

> I can't believe that none of the functional ninjas thought to add time travel as a benefit. Most remiss... Ahem: https://hackage.haskell.org/package/tardis

With much delight, I stand corrected.

Haskell perpetually astonishes me. Not only is it, more or less single-handedly, keeping the Holy Wars alive, it now appears to supply punchlines to jokes. Amazing.

Re: How Not to Write a Signal Handler

#35
post #7

Earlier quoted context omitted.

I think the kqueue interface is a lot worse than the Linux way. With kqueue everything is forced through one interface. In Linux it's just file descriptors and epoll to deal with them. It is a nice extension of the "everything is a file" mechanism and it embodies the "do one thing and do it right". This becomes apparent when you look at fs notifications. You've already mentioned how inotify is superior to kqueue. I m…

Bah. This is complete nonsense. EVFILT_VNODE is not complicated to use for the cases for which it was actually designed — monitoring a file descriptor. For more general file system monitoring, a new kqueue filter type would be ideal, but adding that does not require breaking or deprecating kqueue API; the whole point of kqueue is to provide a generic extensible event mechanism. Adding a recursive path monitoring filt…

If you begin your comment with "Bah. This is complete nonsense." then you should at least address all of my points...

Especially when you confirm one thing I've said in your first sentence. EVFILT_VNODE's design it too limited. It can watch directories (which after being opened are just a file descriptor). But it doesn't give you the information you need although they are available when the event is generated. The only explanation for this I can think of is because the API designers wanted to cover every event even if they didn't understand the particular use case. Which is exactly what's going to happen when you try to design an API in such a way.

Yes, you could change kqueue and add another event type. But then why keep EVFILT_VNODE, except for legacy reasons?

You complain about nonsense and then you compare a paper covering kqueue, which again is an API trying to do everything, to the documentation of inotify, which only covers a single class of events. And then you are disingenuous enough to only look at the README and not at the provided manpages and other material. inotify actually has pretty good documentation. But if you want to compare the 30 lines README to the kqueue paper ... well the kqueue paper covers EVFILT_VNODE with 19 lines, 7 of which simply list the possible actions.

inotify is single purpose because it follows the "do one thing and do it right"-principle. The Linux folks had the freedom and time to come up with a good enough API because inotify wasn't forced into epoll, which itself follows the "do one thing and do it right"-principle.

Meanwhile the kqueue designers came up with an fs notification API that is even inferior to what w32 offers...

Re: How Not to Write a Signal Handler

#36
post #4

They write: "It is the 2013th year in the Common Era at the moment of this writing and you might think that people should have came up with something better in terms of signal handling at this time. The truth is that they did. It is just not that well known yet due to a huge momentum of outdated information still overflowing the Internet." Then they talk about kqueue. The above paragraph emphasizes how much Unix prog…

why not talk about soft IRQ?

The signal idea is to implement a user space soft IRQ like communication between process.

But we trigger them the wrong way

if should not be syslog that does kill -HUP daemon to have them release file but daemon that should have callback implemented like "on_file_destroy" and this event should be propagated to the root processes until the bubble up event is being stopped explicitly from being propagated.

The problem with that approach that is simple is it requires a careful definition of defined callbacks

Re: How Not to Write a Signal Handler

#37
post #32

Earlier quoted context omitted.

> I can't believe that none of the functional ninjas thought to add time travel as a benefit. Most remiss... Ahem: https://hackage.haskell.org/package/tardis

With much delight, I stand corrected. Haskell perpetually astonishes me. Not only is it, more or less single-handedly, keeping the Holy Wars alive, it now appears to supply punchlines to jokes. Amazing.

Wouldn't you do the same if you had a time machine?

Re: How Not to Write a Signal Handler

#38
Why does the signal handler have to interrupt a thread? Why doesn't the OS just create a new thread to run the signal handler in? This would avoid this whole reentrancy problem and make the concurrency explicit.

Re: How Not to Write a Signal Handler

#39
post #9

I looked around but couldn't find a great answer on how to do this correctly in Python on Linux. I have a daemon that attempts to shut down cleanly when it gets a number of signals and it appears to be working correctly. But, it's written like the first example.

It is possible to write thread safe signal (and portable) signal handlers doing exactly what you've done. Have the handler set a flag. That's is. Then, outside the handler, periodically check that flag and do the real work when it changes.

It used to be that you needed to make the flag variable "volatile sig_atomic_t" ( http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sign... ). I think nowadays you'd want to use an atomic bool or atomic int.

The main reason I prefer this approach is that sigaction is in the POSIX standard but not the C or C++ standards. sigaction isn't available on Windows, but signal is (then again, very few signals are available on Windows).

Re: How Not to Write a Signal Handler

#40
this seems like yet another case where a thread safe lockless queue would be good. setting a volatile atomically is fine for the simplest cases, but what if you want to handle every signal raised independently and not just do something if any signal is raised?

the real answer here i think is to think about code being run concurrently and how to do that safely... where a signal handler is a special case that, actually, requires no extra special treatment.

Post reply on HN