diff --git a/bin/daemon_with_pidfile b/bin/daemon_with_pidfile
new file mode 100755
index 0000000000000000000000000000000000000000..f138c27a0e2b85374a5f874a633163b864e04eb1
--- /dev/null
+++ b/bin/daemon_with_pidfile
@@ -0,0 +1,33 @@
+#!/usr/bin/env ruby
+# daemon_with_pidfile
+#
+# Daemonize, write a pidfile, and exec the remainder of the command line.
+
+def main(pidfile, cmd)
+  if middle_pid = Process.fork
+    # outer process
+    # Do not exit the outer process before the middle process finishes
+    Process.waitpid(middle_pid)
+    exit $?.exitstatus
+  end
+
+  if final_pid = Process.fork
+    # middle process
+    open(pidfile, 'w') { |f| f.puts final_pid }
+    exit
+  end
+
+  # Standard daemon things: become session leader, ignore SIGHUP, close stdin.
+  Signal.trap("HUP", "IGNORE")
+  Process.setsid
+  IO.new(0).close
+
+  exec(*cmd)
+end
+
+if ARGV.count < 2
+  abort "Usage: #$0 pidfile command [args...]"
+end
+
+pidfile = ARGV.shift
+main(pidfile, ARGV)
diff --git a/bin/mail_room b/bin/mail_room
index f4f1a170c042b763bf484cee28a5252e5a380dd5..74a84f5b2b477d64441989633a3b68963a4d1db5 100755
--- a/bin/mail_room
+++ b/bin/mail_room
@@ -19,9 +19,7 @@ get_mail_room_pid()
 
 start()
 {
-  bundle exec mail_room -q -c $mail_room_config >> $mail_room_logfile 2>&1 &
-  PID=$!
-  echo $PID > $mail_room_pidfile
+  bin/daemon_with_pidfile $mail_room_pidfile bundle exec mail_room -q -c $mail_room_config >> $mail_room_logfile 2>&1
 }
 
 stop()