Question

I have a command-line application called xooky_nabox that was programmed using c++. It reads a puredata patch, processes signals from the audio in jack of a beagleboard and outputs signals through the audio out jack.

I want the application to run wen the beagleoard starts up and stay running until the board is shut down. There is no GUI and no keyboard or monitor attached to it, just the audio in and out jacks.

If I run the application manually everything works fine:

xooky_nabox -audioindev 1 -audiooutdev 1 /var/xooky/patch.pd

And it also runs fine if I run it in the background:

xooky_nabox -audioindev 1 -audiooutdev 1 /var/xooky/patch.pd &

Now, let me show the code layout of two versions of the program (The full thing is at https://github.com/rvega/XookyNabox):

Version 1, main thread is kept alive:

void sighandler(int signum){
  time_t rawtime;
  time(&rawtime);

  std::ofstream myfile;
  myfile.open ("log.txt",std::ios::app);
  myfile << ctime(&rawtime) << "   Caught signal:" << signum << " " << strsignal(signum) << "\n";
  myfile.close();
  if(signum == 15 || signum == 2){
     exit(0);
  }
}


int main (int argc, char *argv[]) {
   // Subscribe to all system signals for debugging purposes.
   for(int i=0; i<64; i++){
      signal(i, sighandler);
   }   

   // Sanity checks, error and help messages, etc.
   parseParameters(argc, argv);

   //Start Signal processing and Audio
   initZenGarden();
   initAudioIO();

   // Keep the program alive.
   while(1){
      sleep(10);
   }

   // This is obviously never reached, so far no problems with that...
   stopAudioIO();
   stopZengarden();

   return 0;
}

static int paCallback( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData ){
   // This is called by PortAudio when the output buffer is about to run dry.
}

Version 2, execution is forked and detached from the terminal that launched it:

void go_daemon(){
   // Run the program as a daemon.
   pid_t pid, sid;
   pid = fork(); // Fork off the parent process
   if (pid < 0) {
      exit(EXIT_FAILURE);
   }
   if (pid > 0) {
      exit(EXIT_SUCCESS); // If child process started ok, exit the parent process
   }
   umask(0); // Change file mode mask

   sid = setsid(); // Create a new session ID for the child process
   if (sid < 0) {
      // TODO: Log failure
      exit(EXIT_FAILURE);
   }

   if((chdir("/")) < 0){ //Change the working directory to "/"
      //TODO: Log failre
      exit(EXIT_FAILURE);
   }

   close(STDIN_FILENO);
   close(STDOUT_FILENO);
   close(STDERR_FILENO);
}

int main (int argc, char *argv[]) {
   go_daemon();      

   // Subscribe to all system signals for debugging purposes.
   for(int i=0; i<64; i++){
      signal(i, sighandler);
   }   

   // Sanity checks, error and help messages, etc.
   parseParameters(argc, argv);

   //Start Signal processing and Audio
   initZenGarden();
   initAudioIO();

   // Keep the program alive.
   while(1){
      sleep(10);
   }

   // This is obviously never reached, so far no problems with that...
   stopAudioIO();
   stopZengarden();

   return 0;
}

Trying to run it at startup

I've tried running both versions of the program at startup using a few methods. The outcome is always the same. When the beagle starts up, I can hear sound beign output for a fraction of a second, the sound then stops and the login screen is presented (I have a serial terminal attached to the board and minicom running on my computer). The weirdest thing to me is that the xooky_nabox process is actually kept running after login but there is no sound output...

Here's what I've tried:

Adding a @reboot entry to crontab and launching the program with a trailing ampersand (version 1 of the program):

@reboot   xooky_nabox <params> &

Added a start-stop-daemon to crontab (version 1):

@reboot start-stop-daemon -S -b --user daemon -n xooky_nabox -a /usr/bin/xooky_nabox -- <params>

Created a script at /etc/init.d/xooky and did

$chmod +x xooky
$update-rc.d xooky defaults

And tried different versions of the startup script: start-stop-daemon with version 1, calling the program directly with a trailing ampersand (version 1), calling the program directly with no trailing ampersand (version 2).

Also, if I run the program manually from the serial terminal or from a ssh session (usb networking); and then I run top, the program will run fine for a few seconds consuming around 15% cpu. It will then stop outputing sound, and it's cpu consumption will rise to around 30%. My log.txt file shows no signal sent to the program by the OS in this scenario.

When version 2 of the program is ran at startup, the log wil show something like:

Mon Jun  6 02:44:49 2011 Caught signal:18 Continued
Mon Jun  6 02:44:49 2011 Caught signal:15 Terminated

Does anyone have any ideas on how to debug this? Suggestions on how to launch my program at startup?

Was it helpful?

Solution 3

I ended up ditching PortAudio and implementing a JACK client which runs it's own server so this issue was not relevant for me anymore.

OTHER TIPS

In version 2, I think you should open (and dup2) /dev/null to STDIN/STDOUT/STDERR. Just closing the handle would cause problem.

something like this:

int fd = open("/dev/null", O_RDWR);
dup2( fd, STDOUT_FILENO );

(I have no idea what start-stop-daemon do. Can't help version 1, sorry)

There is C function to create a daemon

#include <unistd.h>

int daemon(int nochdir, int noclose);

More information can be found in man pages for daemon(3) Maybe it will help.

And if you want to launch you daemon when you linux start, you should find out which init version you are using in you distro, but usually, you can just add command to execute you daemon to /etc/init.d/rc (but it seems to be no so good idea). This file is executed by init when linux is starting.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top