[OSM-dev] mod_tile PID file

Troy Wu troywu at yahoo.com
Wed Apr 2 00:19:57 UTC 2014

Howdy, all.

New here.  Just built an OSM tile-server "manually" against Ubuntu 12.04 LTS, and wanted to have multiple rendering pipelines.  It wasn't hard to get a virtual-hosts setup running to have multiple apache ports.  Obviously, the trick was to get multiple renderd's running.  I refer to this message in the archives:

==> https://lists.openstreetmap.org/pipermail/dev/2011-March/022157.html

[Specifically, the part about how the source contains a hard-coded PID file path.]

So, I patched daemon.c (and two include files) in mod_tile to take "pid_file" in renderd.conf.  I did this to run multiple renderd instances, and still have them maintain compatibility with Ubuntu's init scripts (specifically, start-stop-daemon).  I've included the diff inline at the bottom (it's not formatted or cleaned up; I wanted my changes to visually be obvious to me while I was hacking).

I'm able to achieve a config file like this:

[/usr/local/bin] # head -6 /usr/local/etc/renderd.conf

I did have to make one rather kludgy hack; for each instance of renderd I wanted to start, I would have to copy the EXECUTABLE file:

	$ cp renderd renderd-other-instance

I had to do this because Ubuntu's start-stop-daemon (which is an executable, so changing it would be non-trivial) apparently aggressively looks for the executable when it goes to stop a daemon.  If there were still processes running whose name matched the daemon we were shutting down, it would shut them ALL down.  I tried a symlink, but start-stop-daemon must resolve the link, because that didn't work; I thought about a hardlink--which might--but didn't want to litter /usr/local/bin with hardlinks.  So, I'm stuck with having a copy.  It's not the disk space is an issue; it's just messy.

Having said all that...This works.  I can create a rc2.d/S80renderd and an rc2.d/S80renderd-other-instance which point to their respective entries in /etc/init.d.  Of course, I had to duplicate the init.d/renderd file (so there are 2, /etc/init.d/renderd and /etc/init.d/renderd-other-instance).  The file looks like this (obviously, my alternative instance is called "renderd-dark"):

# PATH should only include /usr/* if it runs after the mountnfs.sh script
DESC="Mapnik rendering daemon-dark"
DAEMON_ARGS="-c /usr/local/etc/${NAME}.conf"

And, its config file starts like this:


This is obviously clunky.  Still, it seems like having multiple rendering pipelines per PostGIS instance is something that some people would like to have.  It also seems like an obvious use of a datasource, since so much of the in deploying a tile server is getting the database up, imported, and kept-up-to-date.  Of course, I suppose it's possible to run separate servers (which in a Xen/KVM environment might make sense), and keep things clean.  OTOH, if someone is just experimenting with one server, it doesn't seem unreasonable.

I'd appreciate hearing thoughts on this.


[~/new/mod_tile-20140323] $ diff -u src/daemon.c-ORIG src/daemon.c
--- src/daemon.c-ORIG	2014-04-01 16:03:02.480526420 -0700
+++ src/daemon.c	2014-04-01 16:39:22.500978149 -0700
@@ -807,6 +807,8 @@
             sprintf(buffer, "%s:socketname", name);
             config_slaves[render_sec].socketname = iniparser_getstring(ini,
                     buffer, (char *) RENDER_SOCKET);
+sprintf(buffer, "%s:pid_file", name);
+config_slaves[render_sec].pid_path = iniparser_getstring(ini, buffer, (char *) PID_PATH);
             sprintf(buffer, "%s:iphostname", name);
             config_slaves[render_sec].iphostname = iniparser_getstring(ini,
                     buffer, "");
@@ -828,6 +830,7 @@
                 config.ipport = config_slaves[render_sec].ipport;
                 config.num_threads = config_slaves[render_sec].num_threads;
                 config.tile_dir = config_slaves[render_sec].tile_dir;
+                config.pid_path = config_slaves[render_sec].pid_path;
                         = config_slaves[render_sec].stats_filename;
                 config.mapnik_plugins_dir = iniparser_getstring(ini,
@@ -852,6 +855,7 @@
         syslog(LOG_INFO, "config renderd: num_slaves=%d\n", noSlaveRenders);
     syslog(LOG_INFO, "config renderd: tile_dir=%s\n", config.tile_dir);
+syslog(LOG_INFO, "config renderd: pid_path=%s\n", config.pid_path);
     syslog(LOG_INFO, "config renderd: stats_file=%s\n", config.stats_filename);
     syslog(LOG_INFO, "config mapnik:  plugins_dir=%s\n", config.mapnik_plugins_dir);
     syslog(LOG_INFO, "config mapnik:  font_dir=%s\n", config.mapnik_font_dir);
@@ -913,7 +917,8 @@
             fprintf(stderr, "can't daemonize: %s\n", strerror(errno));
         /* write pid file */
-        FILE *pidfile = fopen(PIDFILE, "w");
+        /* FILE *pidfile = fopen(PIDFILE, "w"); */
+FILE *pidfile = fopen(config.pid_path, "w");
         if (pidfile) {
             (void) fprintf(pidfile, "%d\n", getpid());
             (void) fclose(pidfile);

[~/new/mod_tile-20140323] $ diff -u includes/render_config.h-ORIG includes/render_config.h
--- includes/render_config.h-ORIG	2014-04-01 16:12:13.845813330 -0700
+++ includes/render_config.h	2014-04-01 16:13:23.271480920 -0700
@@ -9,6 +9,7 @@
 // With directory hashing enabled we rewrite the path so that tiles are really stored here instead
 #define HASH_PATH "/var/lib/mod_tile"
+#define PID_PATH "/var/run/renderd/renderd.pid"
 // TILE_PATH is where Openlayers with try to fetch the "z/x/y.png" tiles from
 // this is now only used if DIRECTORY_HASH is undefined

[~/new/mod_tile-20140323] $ diff -u includes/daemon.h-ORIG includes/daemon.h
--- includes/daemon.h-ORIG	2014-04-01 16:17:51.549926893 -0700
+++ includes/daemon.h	2014-04-01 16:18:10.582384187 -0700
@@ -22,6 +22,7 @@
     int ipport;
     int num_threads;
     char *tile_dir;
+    char *pid_path;
     char *mapnik_plugins_dir;
     char *mapnik_font_dir;
     int mapnik_font_dir_recurse;

More information about the dev mailing list