lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Alexander Gladysh once stated:
> Hi, Brian!
> 
> I see that lib-ev has signal handling support in TODO section.
> 
> What is the status of this feature? Is it hard to implement?

  Signal handling is hard to do in general.  I spent over a month [1]
tracking down a bug caused by a signal handler, and if you are attempting to
write code to work across multiple operating systems, the *only* thing you
can do safely in a signal handler is set a variable of type sig_atomic_t. 
That's it.

  *If* you can restrict yourself to Posix semantics, then the number of
things you can do goes up, but you *still* have to be very careful (it helps
to realize that once you start writing signal handlers, you're writing
multithreaded code).

  I know in my syslog replacement [2], the code looks like (and sorry, this
part is in C):

volatile sig_atomic_t mf_sigint;
volatile sig_atomic_t mf_sigusr1;
volatile sig_atomic_t mf_sighup;
volatile sig_atomic_t mf_sigalarm;

void handle_signal(int sig)
{  
  switch(sig)
  {
    case SIGTERM: mf_sigint   = 1; break;
    case SIGINT:  mf_sigint   = 1; break;
    case SIGUSR1: mf_sigusr1  = 1; break;
    case SIGHUP:  mf_sighup   = 1; break;
    case SIGALRM: mf_sigalarm = 1; break;
    default: break;
  }
}


  /* ... */

  set_signal_handler(SIGINT, handle_signal);
  set_signal_handler(SIGUSR1,handle_signal);
  set_signal_handler(SIGHUP ,handle_signal);
  set_signal_handler(SIGALRM,handle_signal);
  set_signal_handler(SIGTERM,handle_signal);

  while(!mf_sigint)
  {
    assert(lua_gettop(g_L) == 0);
    
    if (mf_sigusr1)
    {
      mf_sigusr1 = 0;
      load_script();
    }

    if (mf_sighup)
    {
      mf_sighup = 0;
      call_optional_luaf("reload_signal");
    }
    
    if (mf_sigalarm)
    {
      mf_sigalarm = 0;
      call_optional_luaf("alarm_handler");  
    }
    
    if (poll(events,g_maxsocket,-1) < 1)
      continue; /* continue on errors and timeouts */
    
    for (size_t i = 0 ; i < g_maxsocket; i++)
    {
      if ((events[i].revents & POLLIN))
        event_read(&g_sockets[i]);
    }
  }

  /*------------------------------------------------------------------------
  ; Per http://www.cons.org/cracauer/sigint.html, the only proper way to
  ; exit a program that has received a SIGINT (or SIGQUIT) is to actually
  ; use the default action of SIGINT (or SIGQUIT) so that the calling
  ; program can detect that the child process (in this case, us) actually
  ; received a signal.  So that's why we set the default handler for SIGINT
  ; and kill ourselves, since the only way we get here is via SIGINT (or
  ; possibly SIGQUIT if/when I add logic for that).
  ; (I found this *just today!*)
  ;------------------------------------------------------------------------*/
  
  set_signal_handler(SIGINT,SIG_DFL);
  kill(getpid(),SIGINT);

  If I need other signals, I'll add them in C, not in Lua.  But, I also have
control over the Lua code, and I can make sure to avoid infinite loops in
the Lua code.   And so far, this has been running solidly for months [3].

  -spc (One of these days I'll get around to releasing the syslogd
	replacement)

[1]	http://boston.conman.org/2007/10/18.1

[2]	http://boston.conman.org/2010/02/09.1

[3]	Not to say there aren't issues---because of some of the code I'm
	using when logging system messages (this is, after all, a
	replacement for syslogd) causes problems on my home system when I
	power up.  It's an odd interaction between the network, iptables,
	initlog [4] and a Lua script run by my syslogd replacement.  I
	haven't fully solved that issue yet.

[4]	Yes, it's on a RedHat derived Linux distribution.  Much hate, but
	that's a post for another mailing list [5]

[5]	Hates Software