Game Development Community

Deamonizing A Dedicated Server

by Scott Doerrfeld · in Torque Game Engine · 09/09/2007 (2:21 pm) · 9 replies

I was wondering if anyone could offer me some guidance with daemonizing my dedicated server for Linux. I need my server to start when the machine gets booted up and run as a daemon that can be stopped/restarted.

#1
09/09/2007 (3:52 pm)
Would I put a call to a daemonizing function in the DemoGame::main() game loop that is part of game/main.cc?
#2
09/09/2007 (4:44 pm)
Write a short wrapper script to restart it if it breaks, and run it inside of a screen.

Gary (-;
#3
09/09/2007 (5:17 pm)
I'd love to use screen but my server administrators are saying "No, must daemonize!"
#4
09/10/2007 (11:22 am)
Time to pull out Stephens [anyone doing any serious unix programming needs this book].

1) Fork and kill parent
int i;
i = fork();
if(0 > i) {
  perror("Error in fork")
  exit(1);
} else if (0 < i) {
  exit(0); // Kill Parent
}

2) Create a new session
setsid();

3) Close all open file descriptors, and hook srd{in,out,err} to something harmless
int i,j;
for (i=getdtablesize();0<=i;i--)
  close(i);
// open() will allocate file handles sequentially. First one will be zero, then 1, then 2, for stdin,out,err
j=open("/dev/null", O_RDWR);
j=dup(j);
j=dup(j);

4) chdir to somewhere appropriate. For us, this means chdir into the game dir.
chdir(dirname(argv[0]))

5) Set your file mask appropriately.
umask(0)

Thar you have it. 101 of daemon writing, /a la/ stephens. For various torque-ish reasons, I would suggest you add this code right at the start of your application's execution. It's also good karma to fork() again after creating a new session, but I left it out for clarity.

Gary (-;
#5
09/10/2007 (1:16 pm)
@Gary: Thanks a bunch! So "at the start of your application's execution" would be where I've mentioned above, right?
#6
09/10/2007 (2:29 pm)
I'm not sure which version of the SDK you have, I think demogame::main should actually be game::main. Demogame was soemthing odd that popped up for a while. But yes, in the body of the appropriate instance of GameInterface::Main() is the place to do it.

It's platform-specific code, so you should probably create a function, like, Platform::DaemoniseForReals(const char *path), put in stubs on windows and mac platforms, and put the code I put there in the linux platform. That way you don't need to make any platform-specific changes to the non-platform-specific codebase, and determined windows and mac coders can destubbify their platform code to make Torque run as a service on windows, or a whatever-macs-do on macs.

Gary (-;
#7
09/17/2007 (1:18 pm)
My daemon program kept exiting and I finally figured out where. It exits here in DemoGame::main before it even gets to the game loop:

// Set up the command line args for the console scripts...
   Con::setIntVariable("Game::argc", argc);
   U32 i;
   for (i = 0; i < argc; i++)
      Con::setVariable(avar("Game::argv%d", i), argv[i]);
   if (initGame(argc, argv) == false)
   {
      Platform::AlertOK("Error", "Failed to initialize game, shutting down.");
      shutdownGame();
      shutdownLibraries();
      gShuttingDown = true;
      return 0;
   }

I am not sure why but running as a daemon it fails to initialize. Should I be daemonizing after the call to initGame perhaps? Thanks for your help.
#8
09/17/2007 (1:28 pm)
Oh whoops i didn't chdir into the game dir like you said...i'll try that

@Gary: I am not sure how do we get the game directory?
#9
09/17/2007 (2:48 pm)
Quote:@Gary: I am not sure how do we get the game directory?

ahahaha.

Congratulations, you win a cookie for asking the question I accidentally-on-purpose left unanswered in my code post. It's actually a nonsimple question to answer, and even more nonsimple to do from C.


Originally, I said this:
chdir(dirname(argv[0]));
Which will chdir to the path prefix from your command line. The problem is thus: If you're using "cd game-path; torqueDemo.bin" to run the command, this will have both irritating and unpredictable results. For a start, take "." out of your path; it's #1 security risk easy mistake to make.

If you're using "./torqueDemo.bin" or "/usr/local/games/MyGame/torqueDemo.bin", chdir(dirname(argv[0])) should work.

The easiest way to do this in a portable-to-all-unices-except-maybe-OSX way is by running your game binary from a script, instead of having users run the binary directly. Then prefix the correct path on your binary using a script. It sounds so easy.

Conveniently, if you look in your example/ dir in your torque SDK install, you'll find a script called "runtorque.sh", which contains a bourne script function, "FindPath()" written by a nice gentleman named Sam Lantinga, working at Loki almost eight years ago now. If you look in almost any recent commercial game [including quakes and unreals, all games Loki put out...], you'll find that they do exactly this.


So, Short answer: Use Sam's FindPath() function in a wrapper script that executes the binary with its full path prefixed.

Hope that helps, albeit in a slightly rambling and wordy way.

Gary (-;

PS You should also use a debugger to find out exactly *where* initGame is returning. It may be balking on the slightly funky filehandles, or something.