The self-pipe trick isn't a perfect replacement for signalfd, because the signals aren't blocked. Blocked signals don't cause EINTR when they're received.
When working on OS X (and presumably BSD), you can use kqueue (the OS X man page is comprehensive) to watch for signal delivery. The same SIG_BLOCK requirement applies.
(Whether this is a practical matter, on the other hand, I'm not sure... if your main loop is based around select/poll/kqueue/etc., you probably won't be making any calls that would block anyway. And I'm not even sure that avoiding EINTR is such a great idea in the first place, though obviously if you have to block it to use signalfd/kqueue then you must. But it's actually quite a useful error to receive, and fits in quite neatly with level-triggered polling.)
When working on OS X (and presumably BSD), you can use kqueue (the OS X man page is comprehensive) to watch for signal delivery. The same SIG_BLOCK requirement applies.
(Whether this is a practical matter, on the other hand, I'm not sure... if your main loop is based around select/poll/kqueue/etc., you probably won't be making any calls that would block anyway. And I'm not even sure that avoiding EINTR is such a great idea in the first place, though obviously if you have to block it to use signalfd/kqueue then you must. But it's actually quite a useful error to receive, and fits in quite neatly with level-triggered polling.)