Я просмотрел glibc 2.24, который поставляется с Debian 9.
posix _spawnp (и posix _spawn )реализованы как пользовательский -код C режима, а не системный вызов. Он делает следующее:
O_CLOEXEC
. CLONE_VFORK
. vfork ограничивает связь между дочерними и родительскими -здесь в игру вступает канал. ec
в 0. Если чтение завершается успешно, ec
— это код ошибки, отправленный ему потомком. ec
. Я выделил эти слова курсивом, потому что это ошибка.
Когда posix _spawnp выполняет все эти posix_spawn_file_actions_addclose
действия, код glibc достаточно умен, чтобы дублировать конец записи канала, когда он видит действие файла, которое влияет на этот файловый дескриптор.
int p = args->pipe[1];
...
/* Dup the pipe fd onto an unoccupied one to avoid any file
operation to clobber it. */
if ((action->action.close_action.fd == p)
|| (action->action.open_action.fd == p)
|| (action->action.dup2_action.fd == p))
{
if ((ret = __dup (p)) < 0)
goto fail;
p = ret;
}
Проблема в том, что дубликат не дублирует флаг O_CLOEXEC
, поэтому fd передается процессу, который был запущен дочерним процессом, и не будет закрыт, пока этот процесс не завершится. Чтение в родительском элементе не вернется, пока это не произойдет.
Ошибка была исправлена в этой фиксации . Теперь потомок сообщает об успехе или неудаче родителю, используя общую переменную вместо канала.
Если вы застряли с этой версией glibc,вы ничего не можете сделать, кроме как не сообщать posix _spawnp закрыть конец записи канала (вероятно, logfd+2 в вашем примере кода ).
Для этого не нужно использовать два awk-скрипта, достаточно одного.
awk 'length($0) == 23 { print ; next };
/^FEPS/ { line=$0; next };
{
line = line $0;
if (length(line) == 23) print line;
line="";
}
' input
Вывод после сохранения исходного примера в файл с именемinput
:
FEPS xxxx01 BUILDING 0
FEPS xxxx03 BUILDING 0
FEPS xxxx04 BUILDING 0
$ cat tst.awk
$1 == "FEPS" { prt(); rec="" }
{ rec = rec $0 }
END { prt() }
function prt() { if (length(rec) == 23) print rec }
$ awk -v n=23 -f tst.awk file
FEPS xxxx01 BUILDING 0
FEPS xxxx03 BUILDING 0
FEPS xxxx04 BUILDING 0