конфликт readline с дочерним printf? - PullRequest
0 голосов
/ 28 сентября 2010

В Linux readline () в бесконечном цикле постоянно читает text \ n. Однако, как только дочерние процессы начинают печатать на экране, readline больше не читает новых строк. Даже если я неоднократно нажимаю клавишу ввода, readline () не возвращается.

Кто-нибудь знает, что не так?

Пример кода по запросу:

char* input;
int cpid;
while(1)
{
     input = readline(">>>");
     strcpy(tempInput, input); //...does some stuff w/ tempInput
     //....
     cpid = fork();
     if(cpid == 0){
           printf("..."); printf("...");
           execl("ls", "ls", "-l", (char*) NULL); //sample execl parameters
     }
     else{
           //do some stuff...
           printf("...");
     }
     free(input);
}

    //readline(">>>") works the first time and doesn't return on subsequent calls

Отслеживание стека, где код висит (навсегда):

Thread [1] (Suspended : Signal : SIGINT:Interrupt)  
    __read_nocancel() at ../sysdeps/unix/syscall-template.S:82 0x7ffff78f0490   
    rl_getc() at 0x7ffff7bc3727 
    rl_read_key() at 0x7ffff7bc3c90 
    readline_internal_char() at 0x7ffff7baf25f  
    readline() at 0x7ffff7baf795    
    main() at /home/.../.../xxx.c:95 0x4010a1   

Редактировать: Это, вероятно, звучит как полный техноаббл для опытных разработчиков Unix, но мог ли дочерний процесс как-то «захватить» стандартный ввод и не каким-то образом его не выпустить?

Ответы [ 3 ]

1 голос
/ 29 сентября 2010

Ваш дочерний процесс, даже после exec, все еще имеет стандартный вход, подключенный к вашему терминалу. Либо используйте wait(), чтобы дождаться завершения дочернего процесса, либо повторно откройте стандартный ввод дочернего процесса как /dev/null:

close(STDIN_FILENO) && open("/dev/null", "O_WRONLY");
1 голос
/ 06 января 2011

Этот фрагмент кода не работает, потому что ваш вызов execl () завершается неудачно, поэтому дочерний процесс возобновляет работу с кодом цикла, который также будет использовать readline ().

Вы должны передатьполный путь к исполняемому файлу при использовании execl () или использовании варианта execlp () (который ищет переменную окружения PATH), чтобы он работал.

Даже для самых простых системных вызовов рекомендуется всегда проверятьдля их кодов возврата.

1 голос
/ 29 сентября 2010

После того, как вы выполните fork (), ваш дочерний процесс выполняет 2 вызова printf, а затем продолжает выполнение цикла while (1), поэтому вы создаете 1 дополнительный процесс после каждой новой строки.

Что вам нужно сделать, это убить ребенка сразу после того, как он напечатает 2 эллипса (...)

Измените свой код на это:

  if(cpid == 0){
        printf("..."); printf("..."); exec(...); exit(0); 
    }

Помните, что exit () вызывается только в случае сбоя exec ().

Edit:

Если вы намереваетесь принять ввод для какого-либо интерпретатора командной строки, readline - не очень хороший вариант. На его официальной странице написано:

BUGS:

    It’s too big and too slow.

Я мог бы предложить альтернативный способ получения входной строки:

char c;
inputString = calloc(0,sizeof(char));
inputLength = 0;

c = getchar();
    while(c!='\n')
    {
        inputString = realloc(inputString,(inputLength+1)*sizeof(char));
        inputString[inputLength++] = c;
        c = getchar();
    }
    inputString[inputLength] = '\0';

Теперь у вас есть строка в inputString и ее длина в inputLength. Вы могли бы очень хорошо сделать:

execlp(inputString,inputString,0);

для выполнения требуемой функциональности.

...