0

I'm currently programming on an Aldebaran's NAO and I need to execute a shell command from the C++ code, and then get back the output in a buffer. I used the classical method of fork, execve and pipe, but, precisely when I test it in a NAO Module, the pipe doesn't work. I mean, there is no output from the command written in the terminal, but my read() in the parent process waits on STDIN.

What is really strange is that if I just do a simple program to test forks and pipes, with exactly the same command executed, the pipe works.

What is even more strange is that the write(1, "HERE\n", 5) is properly executed and the message is catched back by the read();

My conclusion at this point is that, in a C++ NAO Module, the dup2() works in the child process, but not on the parent one.

Do you guys have any idea of what may be the matter ?

Here is the code :

void
Sonar::getResult()
{
  int pfd[2];
  char buf[4] = { 0, 0, 0, 0 };
  char *arg[] = { "/home/nao/picocom", "-b", "9600", "dev/ttyUSB0", 0 };
  int pid = 0;

  pipe(pfd);

  if ((pid = fork()) == 0)
  {
    close(pfd[0]);
    dup2(pfd[1], 1);

    write(1, "HERE\n", 5);
    int ret = execve(arg[0], arg, 0);

    if (ret == -1)
    {
      close(pfd[1]);
      write(1, "Fail.\n", 6);
      kill(getpid(), 15);
    }
  }

  std::cout << "Pid : " << pid << std::endl;

  close(pfd[1]);
  dup2(pfd[0], 0);
  waitpid(pid, 0, 0);
  int r = read(0, buf, 3);
  close(pfd[0]);

  std::cout << "Read : " << r << std::endl;

  printResult(buf);
}
PinkPR
  • 345
  • 5
  • 13
  • Why do you `dup2` to `STDIN_FILENO` in the parent process? I surely hope you're not expecting to read anything from e.g. `std::cin` after that. Instead you should call `read` with `pfd[0]` as argument. – Some programmer dude Sep 18 '14 at 08:46
  • The problem is the same without the dup2(pfd[0], 0), the return value of the read is 0. – PinkPR Sep 18 '14 at 08:50
  • And if `read` returns zero then the pipe has been closed. Just on a hunch, have you tried moving the `waitpid` call to *after* the `read` call? (Remember that the pipe descriptor is *blocking* so `read` will block until there's something to read.) – Some programmer dude Sep 18 '14 at 08:57
  • I just moved the waitpid after the read, and the read return value is still 0. – PinkPR Sep 18 '14 at 09:07
  • You don't even get the `"HER"` (remember that you only read three bytes) that you explicitly write in the child process? – Some programmer dude Sep 18 '14 at 09:08
  • OK. I tried with a simple 'ls -l', and it works fine, so the matter comes from the picocom binary. This program actually reads what comes from an Arduino on a tty. It must modify something that prevents my read to catch the result of the command. I'll investigate on it ... – PinkPR Sep 18 '14 at 09:10

1 Answers1

0

You should rather use qi::os::spawnvp to spawn processes on NAO. It is cross-platform, by the way. qi::os functions can be found in the include <qi/os.hpp> provided in the NAOqi SDK an also directly in libqi, and are quite useful, even beyond NAO.

Victor Paléologue
  • 2,025
  • 1
  • 17
  • 27