LINUX.ORG.RU

execl не принимает аргумент из pipe (версия 2, обновленная)

 ,


0

3

Есть пример http://www.gnu.org/software/libc/manual/html_node/Process-Creation-Example.html

Слегка модифицировал его, чтобы команда читалась из stdout родителя:


#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
/* Execute the command using this shell program.  */
#define SHELL "/bin/sh"
using namespace std;

int
my_system ()
{
  int status;
  pid_t pid;
 int p[2];
  pipe(p);
  pid = fork ();


  if (pid == 0)
    { //Read
      close(p[1]);
      close(STDIN_FILENO);
      /* This is the child process.  Execute the shell command. */
      dup2(p[0], STDIN_FILENO);

      string str;
      cin >> str;
      execl (SHELL, SHELL, "-c", str.c_str(), NULL);
      _exit (EXIT_FAILURE);
      close(p[0]);
    }
  else if (pid < 0)
    /* The fork failed.  Report failure.  */
    status = -1;
  else
    {
      close(p[0]);
      close(STDOUT_FILENO);
      dup2(p[1], STDOUT_FILENO);
      // close(p[1]);
      string s;
      getline(cin, s);
      cout << s;
      close(STDOUT_FILENO);

    /* This is the parent process.  Wait for the child to complete.  */
      //    if (waitpid (pid, &status, 0) != pid)
      //      status = -1;

    }
  return status;
}

int main()
{
  my_system();
}




но почему-то никакого вывода не происходит.
Что я делаю не так?

UPDATE: обновил код, теперь команда для my_system достается из stdin

UPDATE 2: догадался, что надо делать flush буфера, тогда все работает. (т.е. это проблемы cout)

★★★★

Ответ на: комментарий от DELIRIUM

1894 pipe([3, 4]) = 0
1894 dup2(4, 1 <unfinished ...>
1895 close(4 <unfinished ...>
1894 write(1, «uname -a\n», 9 <unfinished ...>
1895 dup2(3, 0 <unfinished ...>
1895 close(3) = 0
1895 read(0, "", 4096) = 0
1895 execve(0x400ef7, [0x7ffe8236f130], [/* 0 vars */]) = 0

полностью:
http://pastebin.archlinux.fr/1681782

в конце uname проскакивает, но почему-то вывода нет. Но я же stdout не закрывал для child'а...

pashazz ★★★★ ()

Ты сначала форкаешься, а потом уже пайп создаёшь, то есть у тебя получается два никак не связанных друг с другом пайпа.

devsdc ★★ ()
Ответ на: комментарий от devsdc

Точняк, я и не заметил, туплю с утреца. ТС, devsdc дело говорит.

DELIRIUM ☆☆☆☆☆ ()
Ответ на: комментарий от devsdc

Спасибо, не заметил. Теперь работает если я туда просто строки посылаю.

Обновил код, теперь аргумент сначала забирается из stdin. По идее должно работать, но - нет =(

pashazz ★★★★ ()
Ответ на: комментарий от devsdc

а с waitpid'ом вообще подвисает и возвращаться не хочет

pashazz ★★★★ ()
Ответ на: комментарий от pashazz

Я понял почему, breakpoint на execl показал, что возвращается пустая строка, потому что в пайпе к тому времени ничего нет. Ок.

(gdb) print str.c_str()
$2 = 0x7ffff7dda218 <std::string::_Rep::_S_empty_rep_storage+24> ""
(gdb) where
#0  my_system () at fex.cpp:34
#1  0x0000000000400dc0 in main () at fex.cpp:62
(gdb) l 62
57        return status;
58      }
59
60      int main()
61      {
62        my_system();
63      }

(gdb) l 32,35
32            string str;
33            cin >> str;
34            execl (SHELL, SHELL, "-c", str.c_str(), NULL);
35            _exit (EXIT_FAILURE);



Вопрос в следующем. Как заставить child'а ждать появления каких-нибудь данных в пайпе?
И почему, если я в таком варианте кода вызываю waitpid, происходит зависание?

pashazz ★★★★ ()
Последнее исправление: pashazz (всего исправлений: 1)
Ответ на: комментарий от pashazz

Как заставить child'а ждать появления каких-нибудь данных в пайпе?

select, poll, epoll

waitpid, происходит зависание

WNOHANG

DELIRIUM ☆☆☆☆☆ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.