The Boston Diaries

The ongoing saga of a programmer who doesn't live in Boston, nor does he even like Boston, but yet named his weblog/journal “The Boston Diaries.”

Go figure.

Wednesday, May 17, 2000

It's off to the Races

I was right, there were race conditions in monnet. Mark helped me in locating them and my only comment on the whole thing is: Unix signal semantics suck. Although Mark assures me that any form synchronization is nasty, although I still don't see why it has to be so difficult.

To be portable, the only thing you can do in a signal handler is do a simple assignment to a variable declared as volatile sig_atomic_t. Anything else could lead to problems. So, in monnet I now have:

volatile sig_atomic_t g_sigint  = 0;
volatile sig_atomic_t g_sighup  = 0;
volatile sig_atomic_t g_sigchld = 0;

static void handler_int()
{
  g_sigint = 1;
}

static void handler_hup()
{
  g_sighup = 1;
}

static void handler_chld()
{
  int status;

  g_sigchld = 1;
  wait(&status);
}

Granted, that isn't proper ANSI C function headers, but there is no real consensus as to what signal handlers take (on some systems, a single integer parameter, others, no parameters, others several parameters) so that's about the best you can do. I am taking a risk with handler_chld() in doing the wait() but POSIX lists wait() as being callable via a signal handler so hey, why not live on the edge here. Now, elsewhere, the main code:

while(1)
{
  while(1)
  {
    s = read( /* ... */ )
    if (s <= 0) break;
    /* ... */
  }

  if (g_sighup)
  {
    g_sighup = 0;
    generate_report();
  }

  if (g_sigchld)
  {
    g_sigchld = 0;
    g_child   = 0;
  }

  if (g_sigint)
    break;
}

/* ... */

static void generate_report(void)
{
  if (g_child != 0)
    return;

  g_child = fork();

  if (g_child > 0)		/* parent resumes	*/
    return;
  else if (g_child < 0)		/* error?  just resume	*/
  {
    g_child = 0;
    return;
  }

  /* ... */
}

SIGINT just breaks out of the main loop and terminates the program (with some cleanup). SIGHUP generates a call to generate_report() which creates a new process (if one hasn't already been created) to generate the actual report.

If I didn't handle SIGCHLD, I would end up with zombie processes (lovely in that even if I don't care about the child, I still have to wait() for it). Now, it is conceivable that a SIGHUP sent at the right time would fail to create a report file, but would only happen if a previous SIGHUP had been given to generate a report file and was just finishing up. But I can live with that.

Obligatory Picture

[The future's so bright, I gotta wear shades]

Obligatory Contact Info

Obligatory Feeds

Obligatory Links

Obligatory Miscellaneous

You have my permission to link freely to any entry here. Go ahead, I won't bite. I promise.

The dates are the permanent links to that day's entries (or entry, if there is only one entry). The titles are the permanent links to that entry only. The format for the links are simple: Start with the base link for this site: https://boston.conman.org/, then add the date you are interested in, say 2000/08/01, so that would make the final URL:

https://boston.conman.org/2000/08/01

You can also specify the entire month by leaving off the day portion. You can even select an arbitrary portion of time.

You may also note subtle shading of the links and that's intentional: the “closer” the link is (relative to the page) the “brighter” it appears. It's an experiment in using color shading to denote the distance a link is from here. If you don't notice it, don't worry; it's not all that important.

It is assumed that every brand name, slogan, corporate name, symbol, design element, et cetera mentioned in these pages is a protected and/or trademarked entity, the sole property of its owner(s), and acknowledgement of this status is implied.

Copyright © 1999-2024 by Sean Conner. All Rights Reserved.