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.

So, why the double fork?

First of all, let me quote from Bill Karwin:

UDF's that try to change state outside the DBMS (e.g. writing files, starting processes, sending notifications, etc.) are risky. They may take an unbounded amount of time to execute. Or they may be a security vulnerability. Or they may have a bug that makes them crash, which would bring down your MySQL server.

trigger to run an external program

So, we certainly don't want to pause MySQL any longer than necessary (and Lord knows that XXXXXXXX is slow enough), and we don't want MySQL to crash either.

Now, what's the problem with a single fork()? If we do this:

{
  pid = fork();
  if (pid > 0)  /* parent */
    rc = wait(&status);
  else          /* child */
    do_that_thang();
}

we could potentially make MySQL wait too long, say, waiting for the program we shell out to to timeout connecting to a database for instance. We could modify the code to do this:

{
  pid = fork();
  if (pid > 0)  /* parent */
    return;
  else
    do_that_thang();
}

Okay, MySQL doesn't have to wait now, but we have another potential problem and that's when the child process ends. When a process ends, the last thing that needs to happen before the process is truely reclaimed by the kernel is for the parent process to retreive the exit code from the child. And until the parent process does that, the child process is in the ``zombie'' state. It's not quite dead, but it's certainly not alive either.

Granted, MySQL could have set up a signal to handle children dying, but I won't want to count on that. So therefore, what I do is:

{
  pid = fork();
  if (pid > 0)  /* parent */
    rc = waitpid(pid,&status,0);
  else
    do_that_thang();
}

do_that_thang()
{
  pid = fork();
  if (pid > 0)  /* this would be the child process created above */
    exit(0);    /* we kill ourselves, thus letting the parent */
                /* process in MySQL to continue ... */
  else
    really_do_that_thang();
}

When the child process exits, the parent MySQL process gets the exit code and can continue on with its way. The grandchild process looses its parent, which therefore causes the kernel to re-parent the grandchild to init, which is set up to handle orphan child processes exiting.

And that's why the double fork.

Obligatory Picture

[It's the most wonderful time of the year!]

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: http://boston.conman.org/, then add the date you are interested in, say 2000/08/01, so that would make the final URL:

http://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-2019 by Sean Conner. All Rights Reserved.