Ограничение GNU‑Make к POSIX Делает поведение

Короткий ответ

В bashdash) различные "сообщения" состояния задания не отображены от обработчиков сигналов, но требуют явной проверки. Эта проверка выполнена только, прежде чем новая подсказка обеспечивается, вероятно, чтобы не потревожить пользователя, в то время как он вводит новую команду.

Сообщение не показывают непосредственно перед подсказкой после kill отображен, вероятно, потому что процесс еще не мертв - это - особенно вероятное условие с тех пор kill внутренняя команда оболочки, таким образом, это очень быстро для выполнения и не нуждается в разветвлении.

Выполнение того же эксперимента с killall, вместо этого, обычно сразу приводит к "уничтоженному" сообщению, подайте знак, что переключатели/независимо от того, что времени/контекста, необходимые для выполнения внешней команды, вызывают задержку достаточно долго, чтобы процесс был уничтожен, прежде чем управление возвращается к оболочке.

matteo@teokubuntu:~$ dash
$ sleep 60 &
$ ps
  PID TTY          TIME CMD
 4540 pts/3    00:00:00 bash
 4811 pts/3    00:00:00 sh
 4812 pts/3    00:00:00 sleep
 4813 pts/3    00:00:00 ps
$ kill -9 4812
$ 
[1] + Killed                     sleep 60
$ sleep 60 &
$ killall sleep
[1] + Terminated                 sleep 60
$ 

Длинный ответ

dash

В первую очередь, я взглянул на dash источники, с тех пор dash показывает то же поведение, и код, конечно, более прост, чем bash.

Как сказано выше, точка, кажется, что сообщения о состоянии задания не испускаются от обработчика сигналов (который может прервать "нормальный" поток управления оболочки), но они - последствие явной проверки (a showjobs(out2, SHOW_CHANGED) призвать dash) это выполняется только прежде, чем запросить новый вход от пользователя в цикле REPL.

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

Теперь, почему не делает проверки, выполненной сразу после шоу уничтожения, что процесс был на самом деле завершен? Как объяснено выше, вероятно, потому что это слишком быстро. kill внутренняя команда оболочки, таким образом, это очень быстро для выполнения и не нуждается в разветвлении, таким образом, когда сразу после kill проверка выполнена, процесс все еще жив (или, по крайней мере, все еще уничтожается).


bash

Как ожидалось, bash, быть намного более сложной оболочкой, было более хитрым и потребовал некоторых gdb- fu.

След для того, когда то сообщение испускается, является чем-то как

(gdb) bt
#0  pretty_print_job (job_index=job_index@entry=0, format=format@entry=0, stream=0x7ffff7bd01a0 <_IO_2_1_stderr_>) at jobs.c:1630
#1  0x000000000044030a in notify_of_job_status () at jobs.c:3561
#2  notify_of_job_status () at jobs.c:3461
#3  0x0000000000441e97 in notify_and_cleanup () at jobs.c:2664
#4  0x00000000004205e1 in shell_getc (remove_quoted_newline=1) at /Users/chet/src/bash/src/parse.y:2213
#5  shell_getc (remove_quoted_newline=1) at /Users/chet/src/bash/src/parse.y:2159
#6  0x0000000000423316 in read_token (command=<optimized out>) at /Users/chet/src/bash/src/parse.y:2908
#7  read_token (command=0) at /Users/chet/src/bash/src/parse.y:2859
#8  0x00000000004268e4 in yylex () at /Users/chet/src/bash/src/parse.y:2517
#9  yyparse () at y.tab.c:2014
#10 0x000000000041df6a in parse_command () at eval.c:228
#11 0x000000000041e036 in read_command () at eval.c:272
#12 0x000000000041e27f in reader_loop () at eval.c:137
#13 0x000000000041c6fd in main (argc=1, argv=0x7fffffffdf48, env=0x7fffffffdf58) at shell.c:749

Вызов, который проверяет на мертвые задания и co., notify_of_job_status (это - более или менее эквивалент showjobs(..., SHOW_CHANGED) в dash); # 0-#1 связаны с его внутренней работой; 6-8 yacc-сгенерированный код синтаксического анализатора; 10-12 цикл REPL.

Интересное место здесь является № 4, т.е. от где notify_and_cleanup вызов прибывает. Это кажется этим bash, в отличие от этого, dash, может проверить на завершенные задания в каждом символе, считанном из командной строки, но здесь то, что я нашел:

      /* If the shell is interatctive, but not currently printing a prompt
         (interactive_shell && interactive == 0), we don't want to print
         notifies or cleanup the jobs -- we want to defer it until we do
         print the next prompt. */
      if (interactive_shell == 0 || SHOULD_PROMPT())
    {
#if defined (JOB_CONTROL)
      /* This can cause a problem when reading a command as the result
     of a trap, when the trap is called from flush_child.  This call
     had better not cause jobs to disappear from the job table in
     that case, or we will have big trouble. */
      notify_and_cleanup ();
#else /* !JOB_CONTROL */
      cleanup_dead_jobs ();
#endif /* !JOB_CONTROL */
    }

Так, в интерактивном режиме это является намеренным для задержки проверки, пока новая подсказка не обеспечивается, вероятно, для не нарушения пользовательских команд ввода. Что касается того, почему проверка не определяет мертвый процесс при отображении новой подсказки сразу после kill, предыдущее объяснение содержит (процесс еще не мертв).

10
19.10.2018, 13:22
1 ответ
[

]Я почти уверен, что нет способа отключить GNU делать расширения. Цель [].POSIX[] улучшает совместимость, но не отключает совместимые расширения, такие как функции, проприетарные точечные цели, []%[] паттерны в целях и т.д.[

] [

] Я не знаю ни одной реализации, которая бы придерживалась особенностей POSIX. Например, MINIX, Solaris, OpenBSD имеют свои собственные расширения. Вы можете, по крайней мере, попытаться собрать свои программы с этими четырьмя реализациями (предполагая, что ваши программы действительно собираются на всех этих платформах), что даст вам довольно хорошую гарантию переносимости на практике. Добавьте Windows с утилитой []make[] из Visual Studio, плюс порт некоторых оболочек Unix, если вы можете использовать несвободную ОС (думаю, свободной версии VS будет достаточно).[

].
5
27.01.2020, 20:02

Теги

Похожие вопросы