сортировка, вызываемая через дочерний процесс execve, не завершается естественным образом - PullRequest
0 голосов
/ 01 апреля 2019

Я пытаюсь протолкнуть некоторые текстовые файлы через канал, который был дублирован через стандартный сортировщик.Это работает, но это не завершается естественным образом (Интересно, что, кажется, нажатие кнопки «ввод» делает это).

//child
if(rc == 0)
{
    alarm(60);
    close(stdin_pipe_fds[1]);

    close(0);
    dup(stdin_pipe_fds[0]);
    close(stdin_pipe_fds[0]);
    execve("/usr/bin/sort", argv, NULL);
    exit(0);
}

//Parent
if(rc >0)
{
    alarm(60);
    close(stdin_pipe_fds[0]);
    close(stdout_pipe_fds[1]);
    close(stderr_pipe_fds[1]);
    while(fscanf(coolFile, "%1023s", newWord) ==1)
    {
        if(strcmp(newWord, "foobar") != 0)
        {
            write(stdin_pipe_fds[1], newWord, (strlen(newWord)+1));
        }
    }
    if(argc == 2)
    {
        write(stdin_pipe, argc[2], 2);
    }
    if(argc == 3)
    {
        write(stdin_pipe, argc[3], 2);
    }
}

}

Есть идеи?

1 Ответ

0 голосов
/ 02 апреля 2019

Вот более простой способ показать тот же эффект:

$ cd /
$ ls -1 &                              # 1
[1] 58745
myuser@myhost / $ Applications         # 2
Library                                # 3
Network
System
Users
Volumes                                # 4
  1. Команда запускается в фоновом режиме.
  2. Вы получаете ваше приглашение обратно
  3. Вывод команды начинает перезаписывать приглашение
  4. Фоновая команда завершается, но это не приводит к перерисовке приглашения.Поскольку вы не видите приглашение (оно было удалено на шаге № 2), вы думаете, что процесс все еще выполняется.
  5. Когда вы нажимаете ввод, приглашение перерисовывается.Так как теперь у вас снова появляется видимая подсказка, вы неправильно думаете, что Enter вызвал выход из программы.

Вместо этого вы могли бы просто слепо набрать echo "Hello World" и нажать Enter, и вы бы увидели, чтооболочка отвечает отлично.Это чисто косметическая проблема.

Чтобы это исправить, вы должны:

  1. иметь родителя wait() для ребенка, чтобы он не выходил раньше, чем ребенок.
  2. Убедитесь, что родитель полностью закрывает канал ( до ожидания).Ранее ваш родитель немедленно вышел и закрыл канал.Так как теперь он будет ждать дочернего элемента, вы должны вручную закрыть канал, чтобы избежать тупиковой ситуации, когда родительский объект ожидает выхода дочернего элемента, в то время как дочерний элемент ожидает продолжения или завершения родительского действия.
...