login

Forks and Children published on Jun 2, tagged with c, linux

While writing a small learning exercise in C, I came across a nifty little concept. The task itself was a common one: I wanted to spawn a subprocess to the background while letting the main process continue to loop.

Many thanks go to falconindy who spoon fed me quite a bit as I was wrapping my head around all of this knowledge I’m now shamelessly presenting as my own.

In most languages you have some facility to group code into a logical unit (a haskell function or a bash subshell) then pass that unit to a command which forks it off into the background for you (haskell’s forkProcess or bash’s simple &).

Forking C

C takes a far different, but I’d say more elegant, approach. C provides a function, fork() which returns a pid_t.

The beauty of fork() is in its simplicity. All it does is create an exact copy of your program in its current state in memory. That’s it.

int main() {
    pid_t pid;

    pid = fork();

    // ...
}

Guess what, now you’ve got two copies of your running program, both sitting at the exact spot where pid is being assigned the output of fork().

In the copy that was the original (the parent), pid will be the process id of the other copy (the child). And in that child copy, pid will be assigned 0. That’s it; the full extent of fork().

So how do we use this?

Well, let’s say you’ve got a program (as I did) which should sit and loop forever. When some event happens, we want to take some asynchronous action (in my case throw up a dzen notification).

This is the perfect time to use fork(). We’ll let the main thread run continuously, and fork off a child to do its thing when the triggering event occurs.

Here’s a simplified version:

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>

int main() {
    int ret;
    pid_t pid;

    while (1) {
       /* wait for the "event" */
       ret = some_blocking_process();

       if (ret) {
           /* fork it! */
           pid = fork();

           if (pid == 0) {
               /* we are the child, take action! */
               some_action(ret);
               exit(EXIT_SUCCESS);
           }

           /* and the parent loops forever... */
       }
    }
}

So as you can see, the main program waits until some_blocking_process returns an int. If that int is nonzero, we consider that “the event” so we fork to create a copy of ourselves. If pid is zero, we know we are the child process so we take some_action and then simply exit. The parent process will skip that if statement, loop again and wait for some_blocking_process to signal the next event.

Zombie kids

So I may have lied to you slightly about the simplicity of this approach. The above is all well and good – it is simple – but I ran into a small snag while working with my little learner’s app…

Zombies.

Turns out, when a child process exits, it reports its return value to its parent; like any good child should. The child does this by sending a SIGCHLD signal.

The parent then knows if all or some of its spawned children finished successfully or not. This is important if you’ve got some dependant logic or simply want to log that fact.

In my case, I couldn’t care less. Succeed fail, whatever. I’m done with you kid – go away.

Double turns out, if the parent neglects to act on the signal sent from the dying child, it can remain a zombie.

I think this is poor form. I mean, come on, a negligent parent is no reason to make a process wander around aimlessly as a zombie until the next reboot.

Ok, ok, enough with the metaphor. Bottom line – all you need to do to prevent this is install a simple signal handler which will read (and ignore) the status of the child process in response to said signal.

Here’s our same example, but this time with a simple handler added:

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>

static void sigchld_handler(int signum) {
    /* this just silences a compiler warning you might get since we 
     * discard the signum parameter that is passed in */
    (void) signum;

    /* the actual handling of the signal... */
    while (waitpid(-1, NULL, WNOHANG) > 0);
}

int main() {
    int ret;
    pid_t pid;

    struct sigaction sig_child;

    sig_child.sa_handler = &sigchld_handler;
    sigemptyset(&sig_child.sa_mask);
    sig_child.sa_flags = 0;
    sigaction(SIGCHLD, &sig_child, NULL);

    while (1) {
       ret = some_blocking_process();

       if (ret) {
           pid = fork();

           if (pid == 0) {
               some_action(ret);
               exit(EXIT_SUCCESS);
           }
       }
    }
}

That’s it, no more zombies.

I noticed in the source for dzen2 that they use a double-fork approach which also prevents zombies – with no need for signal handlers (yay KISS!):

if (fork() == 0) {
    if (fork() == 0) {
        //
        // child logic...
        //

        exit(EXIT_SUCCESS);
    }

    exit(EXIT_SUCCESS);
}

wait(0);

//
// continue parent logic...
//

I like this approach better.

Android Receiver published on Dec 11, 2010, tagged with android, bash, c, linux

Android notifier is a great little app I just recently found on the marketplace. What it does is use your wifi network or a bluetooth connection to send out a broadcast when certain events happen on your phone.

The idea is to have a companion application running on your computer to listen for the event and pass along the message via some notification system: Growl on Windows/Mac and (I think) gnome-dbus on Linux.

This means your phone can be charging in the other room while you’re at your computer and you’ll get a nice notification on your desktop when someone’s calling you or you get a text.

This is great and all but totally not worth the Gnome or bluetooth library dependencies to get going on Linux. After a brief look at the project’s wiki however I knew I could do something simpler.

I was able to put together two scripts I had already in place to achieve a dead-simple android-receiver on my desktop. The first was a script call ncom which used netcat to send commands across a network and execute them on another machine. The second, bashnotify, was something I was playing around with to get pop-up notifications on track changes in mpd.

Netcat

From the project wiki, I found out that the application will send a broadcast packet on port 10600 in a specific format. After some playing around with test messages I was able to put together the following which successfully echod back the message text in a terminal.

while read -d $'\0'; do
  echo $REPLY
done < <(netcat -z -u -l -p 10600 localhost)

The incoming message doesn’t end with a newline but rather a null character. That’s why using read -d $'\0' and netcats -z option is required. I also found out that I wasn’t getting anything from TCP even though the android app should be broadcasting with both protocols. Using UDP via the -u option seems stable so far.

Dzen

I took the dzen code present in bashnotify and tweaked it a little bit so that the notification temporarily covers my entire status bar and shows the message text:

handle_dzen() {
  local message="$*"

  # dzen settings
  local pipe='/tmp/android-receiver.fifo'
  local delay=4
  local x_offset=0
  local y_offset=0
  local height=17
  local font='Verdana-8'
  local foreground='#ffffba'
  local background='#303030'

  if [[ ! -e "$pipe" ]]; then
    mkfifo "$pipe"
    (dzen2 -ta l -h $height -x $x_offset -y $y_offset \
        -fn "$font" -bg $background -fg $foreground < "$pipe"; rm -f "$pipe") &
  fi

  # todo: make this prettier
  (echo "$message"; sleep $delay) >> "$pipe"
}

And there you go.

The end product is no longer moving my charger away from its normal spot because I’m expecting a call. In stead, I’ll see this:

Android Receiver Screenshot

The source for this script can be found in my github.

In my continued attempts to learn some C, I decided to combine the netcat and message parsing functions of the above into a small C app.

The end result is a nice little program that you can find here. It handles binding to the port, parsing and formatting the message, then handing it off as the first argument to a handler script which is in charge of actually displaying the notification to the user.

To match this functionality, I’ve culled the original script down to only the handle_dzen() function and renamed it to dzen-handler such that it can be used by any application that wants to toss up a brief notification. This script is also available in that android-receiver repo.