В последнее время (без обновления чего-либо и т.п.) начали виснуть иксы при запуске некоторых приложений (замечено за OpenOffice-3 и dosemu). Курсор по экрану движется, но больше ничего не происходит и ctrl-alt-F1/BS/... тоже не работают. Зайдя на машину удаленно и сделав strace -f -p `pgrep '^X$'` , обнаруживаю следующее: --- SIGALRM (Alarm clock) @ 0 (0) --- sigreturn() = ? (mask now []) clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb7c79a78) = ? ERESTARTNOINTR (To be restarted) --- SIGALRM (Alarm clock) @ 0 (0) --- sigreturn() = ? (mask now []) clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb7c79a78) = ? ERESTARTNOINTR (To be restarted) и так без конца. (Те же симптомы: https://qa.mandriva.com/show_bug.cgi?id=33639 ) Порывшись в исходниках иксов на предмет fork, обнаруживаю следующее: ======================================== os/utils.c, в функции Popen: /* Ignore the smart scheduler while this is going on */ old_alarm = signal(SIGALRM, SIG_IGN); if (old_alarm == SIG_ERR) { perror("signal"); return NULL; } switch (pid = fork()) { ==================================================== А вот выше, в функции system, такой предосторожности перед fork() нет. Заблаговременно запущенный strace -f -p также показывает, что в момент (успешного) запуска "проблемных" приложений происходит выполнение xkbcomp: execve("/bin/sh", ["sh"..., "-c"..., "\"/usr/bin/xkbcomp\" -w 1 \"-R/usr/"...], [/ * 26 vars */]) = 0 xkbcomp в исходниках Xorg, действительно, выполняется с помощью System. В исходниках последнего xorg из Сизифа (xorg-x11-server-1.4.0.90-alt21) то же различие: в Popen защита от аларма есть, а в System -- нет. Возможно, ее стоит добавить. У меня самого иксы очень древние (из 4.0.0): xorg-x11-server-1.3.0.0-alt21.M40.1 Да, ещё. Баг не проявляется, если в консоли запущено что-то вроде strace -f -p `pgrep '^X$'` | grep -C5 ^clone Видимо, создаваемой задержки хватает, чтобы цикла не возникало. А вот вывода strace в файл уже недостаточно.
в system оно тоже есть #ifdef SIGCHLD csig = signal(SIGCHLD, SIG_DFL); if (csig == SIG_ERR) { perror("signal"); return -1; } #endif #ifdef DEBUG ErrorF("System: `%s'\n", command); #endif switch (pid = fork()) {
хотя в xorg-server-1.3 этой проверки действительно нет
для 4.0 исправлений уже не будет