One of the advantages of developing applications on Linux (and sharply contrasted with the current trend of smartphone app development) is its robust inter-process communication, which allows things like GNOME Shell extensions that allow you to interact with any media player that supports a specific protocol. D-Bus is currently being used by many Linux applications to enable talking to one another, and since documentation on it is rather sparse, this post will teach you how to write a long-running D-Bus daemon using C and GLib.
This type of design isn’t going to be globally useful for all applications using D-Bus. What it is intended to do is enable small, potentially single-threaded, applications to start up a local “server” unique to them that they can talk to and share. For example, it could be used with Vim to maintain some data in memory that would otherwise cause it to pause or hang, especially if there is some intense calculation or processing involved.
I won’t go into the code itself in great detail, but instead I’m going to cover what it does and why. I recommend keeping it open in another tab or window to provide some context for the rest of this post.
At a high level, what it’s supposed to do is this:
Daemonize. This involves forking the process and telling the parent to quit, then configuring the child to be more daemon-like. I also open up a unix pipe to enable direct communication between the child and parent.
Set up a signal handler. In particular we want to listen for the SIGINT signal to know when to clean up and quit.
Connect to the D-Bus. Rather than creating our own D-Bus server, we just open up a connection to the existing session bus. This will give us a unique name that other applications can use to talk to the daemon. It’s more common for D-Bus applications to create a connection using an owned name like “com.example.MusicPlayer1”, but it’s unnecessary and could cause complications should you want to start two separate instances (if you had two Vim sessions open, for example).
Register an object. D-Bus is built on a model that slightly resembles OOP; messages sent to the daemon will be in the form of method calls or signals on an object. This also requires setting up an interface so that D-Bus knows how to interact with it.
Start listening for requests.
Now, let’s go into more detail.
There are two parts here to daemonizing. First, open up a pipe so that the child and parent can talk to one another after being forked. The reason this is necessary is that we need the parent to report back to the caller what the unique name is for our D-Bus connection, but we won’t know that until the child opens it up. Creating a pipe on Linux is simple:
The pipe() function fills the pipefd array with two file descriptors, one for input and one for output. If it returns -1, then there’s nothing we can do, so we exit right away. The only way pipe() will error out is if the system is out of memory or there are too many open files.
Second, fork the process. For the child, this also involves setting up some more daemon-like behavior, including fully detaching from the parent, resetting the file mask, changing the current directory, closing the standard streams, and opening syslog (with a call to atexit() to ensure it gets closed when the process terminates). For the parent, we first check to make sure the fork worked, and exit if it didn’t. Assuming it worked, then we want to print two things to standard output, one on each line: the PID of the new child process so that we can kill it later, and the unique name from the child’s D-Bus connection. fork() gave us the value of the child’s PID, so we can print that right away, but we need to wait for the child to send the name of the connection across the pipe. Once that’s done, then we can tell the parent to quit.
Everything in main right after the call to daemonize() is running as the child process in daemon mode.
Set up a signal handler
The way to kill a process in Linux is to send it a signal. Pressing Ctrl-C in a terminal or running the command kill -s SIGINT <pid> will send that process the SIGINT signal, which is the operating system politely asking the process to quit. We want to set up a signal handler so that we can exit gracefully.
Connect to the D-Bus
Since we’re using GLib’s bindings to D-Bus, we first need to initialize the type system, hence the call to g_type_init(). After that we create the main loop, but it won’t be started until everything is registered, and open up the connection. For the connection we simply request to join the existing session bus. If it failed, log the error, close the pipe (which will cause the parent to report an empty string as the unique name), and quit. Otherwise, get the unique name of our connection and write it to the pipe, then close it because we don’t need it anymore.
Register an object
Now that we’re connected, we need to register an “object” that will receive the signals and method calls. The actual implementation is defined via XML embedded at the top of the file, so we just tell GLib to parse it and register it with the connection, passing in a vtable that points to the methods handle_method_call(), handle_get_property(), and handle_set_property() for handling various types of requests. Only method calls are fully implemented, but it’s pretty easy to add code to the other handlers to take care of other types of requests.
Start listening for requests
Last but certainly not least, we call g_main_loop_run(), which starts up the main loop that will be listening on our D-Bus connection. Now you can compile it (gio-2.0 is the only dependency), run it, and send it a message:
One of the biggest questions in software design is deciding how to reuse code. There’s no question that it’s necessary; if we rewrote everything from scratch every time, then nothing would ever get built. In general, there are two approaches:
Package the reused code within your application’s executable. This is called static linking, because the reused code is stuck in place and can’t be used by anyone else.
Place the shared code in a location where anyone can access it. This is dynamic linking, because the reused code can be changed and updated independently of who uses it.
There are pros and cons to each approach. Static linking increases program size (in some cases, by quite a lot) but also increases program reliability. Dynamic linking reduces the size of each program, but opens up a new class of problems related to missing libraries and version issues. Windows programs tend to be statically linked and Linux programs tend to be dynamically linked.
About a month ago, I flew out to San Jose, California for an interview with Google. The trip wasn’t exactly planned; I applied to Google for an internship in 2010, and they used the contact info that they had in their system to call me up out of the blue. What recently-graduated computer science student wouldn’t try to take up an offer from arguably the most well-known software company in the world?
To make a long story short, I didn’t get the job, but the whole experience made me question my decision to live in Chicago. I first moved out here from my hometown in Minnesota four years ago to attend DePaul University as an undergrad, for several reasons. First, I love big cities, and the idea of living in Chicago, the largest city in the Midwest by a substantial margin, fascinated me. Second, of the schools I visited, DePaul’s computer school impressed me the most. Granted, I had no clue what to look for in colleges and didn’t visit very many, but even today I feel like I made a good decision. Third, Chicago was far enough from home that I could experience the famed independent college student lifestyle, but close enough that I could still visit regularly. Fourth, the urban setting in Chicago would mean less money spent on transportation (U-Passes are amazing things) and more job opportunities upon graduating.
So I finally got around to experimenting a little bit with Go, a new programming language developed by Google that just recently hit version 1.0. While it seems that most new programming languages are being developed with the goal of becoming “a saner C++,” Go’s intentions are quite different, as highlighted by this statement found in Google’s “A Tour of Go”:
Go does not have classes.
Coming up this weekend is an event that I am rather excited for: the first hackathon hosted by my friends and me, at our new house in Lakeview decked out with ethernet ports and power strips. In particular, we’ll be focusing on game development, so in preparation I’ve begun to organize some ideas and code for the project I hope to make. But, rather than focus on the game itself (which I promise to do in the near future), today I want to talk about the approach I want to use, in particular regarding the use of external libraries.