Ask Your Question
0

Launch Node from code spawns node 2 times and breaks output

asked 2015-09-06 09:40:48 -0600

PhiPhiper gravatar image

updated 2015-09-06 11:21:08 -0600

Hi,

I'm a bit confused. When I try to launch my nav_stack.lauch from my benchmarking code for evaluation purposes and trying to parse the output of it, the output stops. I launch the node via execl and redirect the output to a file that gets later parsed. My call to start the node boils down to:

execl("/bin/bash", "/bin/bash", "-c", "/usr/bin/python /opt/ros/hydro/bin/roslaunch gki_3dnav_benchmark nonenav_stack.launch 2>&1 > navstackoutput.txt", NULL);
When I call the makeplan service from the same code I do get a valid response. But when I take look at the navstackoutput.txt there's no trace of a request getting handled. Here the ouput of ps ax | grep nav_stack:
24328 ?  S  0:00 /bin/bash -c /usr/bin/python /opt/ros/hydro/bin/roslaunch gki_3dnav_benchmark nonenav_stack.launch 2>&1 > navstackoutput.txt
24329 ?  Sl 0:00 /usr/bin/python /opt/ros/hydro/bin/roslaunch gki_3dnav_benchmark nonenav_stack.launch

It seems to me the node starts but another gets started too, which actually handle the requests. Does anyone know how to prevent this? Or do I do something wrong in my execlcall?

PS: I know it's kind of hacky but still the behaviour confuses me. You can find the benchmark project here. As for why I'm doing it this way is that the sbpl outputs some information to stdout that I want to dump in my evaluation database which are not getting published.

Update: Seems the output gets cutoff too when trying the same thing from the shell

roslaunch gki_3dnav_benchmark nonenav_stack.launch > test.txt

The result of the txt where you can see the cutoff:

[ INFO] [1441555720.539266930, 9773.525000000]: Tolerance rot: 0.200000
[ INFO] [1441555720.539284357, 9773.525000000]: Tolerance time: 0.500000
[ INFO] [1441555721.024403188, 9773.861000000]: pluginlib WARNING: In file /tmp/buildd/ros-hydro-clear-costmap-recovery-1.11.16-0precise-20150501-0923/src/clear_costmap_recovery.cpp PLUGINLIB_DECLARE_CLASS is deprecated, please use PLUGINLIB_EXPORT_CLASS instead. You can run the script 'plugin_macro_update' provided with pluginlib in your package source folder to automatically and recursively update legacy macros.  Base = base_class_type, Derived = derived_class_type
[ INFO] [1441555721.025830108, 9
edit retag flag offensive close merge delete

Comments

stdout usually buffers a bunch of data when writing to a file; try checking the output file again after your node has exited and actually written all of its output to disk.

ahendrix gravatar image ahendrix  ( 2015-09-06 11:50:14 -0600 )edit

Would be odd if that's the reason, when executing "sudo find / > test.txt" I got my results in seconds without a hitch. Btw it's a navstack that runs "indefinitely". I do fork the call and the new pipe doesn receive any new data too.

PhiPhiper gravatar image PhiPhiper  ( 2015-09-06 12:11:22 -0600 )edit

A tool like find terminates, and flushes the output buffer when it exits; hence a complete file in that case. Since the navstack doesn't exit and isn't constantly writing, it never fills up the log output buffer, and never needs to flush it to disk.

ahendrix gravatar image ahendrix  ( 2015-09-06 21:24:07 -0600 )edit

I moved on not parsing the output anymore. I deleted the results where you could have seen, that after the cutoff, the killing notification of the node got written. As far as my understanding goes, redirecting stdout to file should always flush the current output, at least when the process exits.

PhiPhiper gravatar image PhiPhiper  ( 2015-09-07 05:35:23 -0600 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2020-09-22 07:35:50 -0600

allenh1 gravatar image

updated 2020-09-22 07:37:47 -0600

As far as I'm aware, you can't redirect files like that with execl. Here's a complete example with redirection written in C (should also compile in C++, but change NULL to nullptr).

Also be sure to source your ROS environment before you execute this.

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char ** argv)
{
  int pid = fork();
  if (-1 == pid) {
    /* fork failed */
    perror("fork");
    return 1;
  } else if (0 == pid) {
    /* child process */
    FILE * fp = fopen("navstackoutput.txt", "w");
    if (NULL == fp) {
      perror("fopen");
      return 1;
    }
    /* get descriptor for the file */
    int fd = fileno(fp);
    /* redirect stderr to stdout */
    dup2(fd, 1);
    /* redirect stdout (and stderr) to the file */
    dup2(fd, 2);
    close(fd);  /* close redundant fd */
    execlp("roslaunch", "roslaunch", "gazebo_ros", "willowgarage_world.launch", NULL);
    perror("execlp");  /* should never get here */
  } else {
    /* parent process */
    printf("Waiting for pid '%d' to exit...\n", pid);
    int status;
    int ret = waitpid(pid, &status, WUNTRACED);
    if (0 > ret) {
      perror("waitpid");
      return 1;
    }
    printf("Child exited with return code '%d'\n", status);
  }

  return 0;
}

I should also note that the process will probably hang until you manually kill it, so you should do a kill -SIGINT [pid] where pid is the number output in the line "Waiting for pid '%d' to exit...".

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2015-09-06 09:40:48 -0600

Seen: 467 times

Last updated: Sep 22 '20