Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is a bracket-like construct for signal handlers possible? #149

Open
jmazon opened this issue Mar 8, 2020 · 2 comments
Open

Is a bracket-like construct for signal handlers possible? #149

jmazon opened this issue Mar 8, 2020 · 2 comments

Comments

@jmazon
Copy link

jmazon commented Mar 8, 2020

I'd like to be a good Unix citizen and restore the signal handlers to the way they were before I meddled with them. Without necessarily ending the process. But all I found that could be used to that effect is installHandler; and while it does provide the former handler, I'm at a loss as to what to restore iset to.

installHandler :: Signal -> Handler -> Maybe SignalSet -> IO Handler
installHandler     int      handler         iset       =  oldhandler

Peeking at the sigaction(3) manpage made matters worse :-) as there's seemingly an additional sa_flags bitset that ought to be restored as well and doesn't appear to be exposed by the current API.

@cartazio
Copy link

Ok. So are you saying that if we wanted to have a withFoo or bracketingSigfoo in Haskell user space the correct hooks aren’t exposed in the current unix/posix packaging?

I’m relatively ignorant about these things myself.

  1. how would you write this sortah code in c ideally?

  2. what would a good wrapper / lift into Haskell look like?

  3. what’s missing to do that well?

@jmazon
Copy link
Author

jmazon commented Mar 14, 2020

Judging by my local (Linux) manpages, the correct scheme in C would be:

#include <signal.h>

void mysigaction(int signo, siginfo_t *info, void *context)
{
  /* do something */
}

int main()
{
  struct sigaction handler, saved;
  handler.sa_handler = NULL;
  sigemptyset(&handler.sa_mask);
  handler.sa_flags = SA_SIGINFO;
  handler.sa_sigaction = mysigaction;

  sigaction(SIGPIPE, &handler, &saved); /* and error handling */

  /* later */

  sigaction(SIGPIPE, &saved, NULL);
  return 0;
}

For a low-level API, I suppose we'd just need a total information-preserving way of saving and restoring the former handler. (the current implementation seems focused on providing a way to implement signal handlers in Haskell, not on providing access to existing C ones. But I'm not convinced I understand 100% of it.)

For a Haskell API, I'm not sure. A form of withSignalHandler sig handler action is always nice. But there's the slight catch that signals are maintained on a per-(Unix-)process basis. I'm not too sure how they relate to Haskell threads, but I wouldn't bet concurrent calls to a hypothetical withSignalHandler ended up in anything sensible.

The current implementation doesn't appear to directly call sigaction via FFI, there's some kind of indirection through stg that rings the "it's probably more complex than seems at first" bell in my head.

AFAIK C programs tend to set the handlers once and for all and not restore them. I ran into this essentially because of GHCi.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants