LINUX.ORG.RU

Когда сигнал может прервать выполнение программы


0

0

Привет!

Рассмотрим ситуацию:
1) Выполняется printf("Hello world\n");
2) Приходит сигнал HUP, который прерывает printf "где-то в середине".
3) В обработчике сигнала я выполняю printf("Fuck world\n");
4) Происходит возврат.

Что будет (точнее может быть) выведено на stdout?

Главный вопрос - в каких местах система может прерывать выполнение
программы?
В любом (где сигнал не блокирован) или есть участки кода, которые
прерваны быть не могут и сингал приходит только после выхода из
этого участка?

Ответ на: комментарий от Krivenok_Dmitry

Со ссылки, которую я дал:

==={{{
when a signal interrupts an unsafe function and the signal-catching
function calls an unsafe function, the behavior is undefined
===}}}

undefined = "в принципе может произойти всё, что угодно."

execve
()
Ответ на: комментарий от Krivenok_Dmitry

> Но ведь реально-то я его могу вызвать.

хм, ваши проблемы и проблемы системы коррелируют только в обратную сторону, но никак не в прямую.

asgard
()

Сигнал может даже прервать системный вызов. Так шо sigprocmask в руки для защиты критических секций.

Zmacs
()

А касательно вопроса "Что будет (точнее может быть) выведено на stdout?" - будет либо

"Hello world\n""Fuck world\n"

либо

"Fuck world\n"

выведено. Hello world во первых попадет в кеш libc-а, а во вторых, блок данных менее чем 512 байт пишеться в дескриптор атомарно.

anonymous
()
Ответ на: комментарий от anonymous

это у меня в системе 512, в Linux-е:

#define PIPE_BUF 4096

anonymous
()
Ответ на: комментарий от anonymous

> А касательно вопроса "Что будет (точнее может быть) выведено на stdout?" - будет либо

Или будет одна из вариаций "Hello woFuck world\nrld\n"

Или, что вероятнее, случится deadlock между двумя printf'ами. google:// printf signal deadlock

execve
()

Нужно смотреть исходиники конкретной libc и определять, реентерабильна (reenterable) ли функция printf. Еще от размера буфера и типа буферизации (функция setvbuf).

В случае LinuxThreads функции libc, вроде бы, используют отдельный мутекс, и тут может случиться и deadlock.

Стандарт четко определяет список функций, которые можно вызывать из обработчика сигнала:

http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html

mky ★★★★★
()
Ответ на: комментарий от execve

> Или будет одна из вариаций "Hello woFuck world\nrld\n"

Только в случае тупой реализации printf-а, посимвольно печатающей строчку, а с корее всего printf готовит строку для записи заранее, по этой причине он будет делать write от готовой строки, а write на размер менее чем PIPE_BUF не будет оборван на куски.

anonymous
()
Ответ на: комментарий от anonymous

Теоретик, млин.

==={{{
$ сat 1.c
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>

static const char *s = "Hello, world";

static void on_sighup()
{
        printf("Fuck world\n");
}

int
main()
{
        struct sigaction act;
        pid_t pid;
        act.sa_handler = on_sighup;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        sigaction(SIGHUP, &act, NULL);
        pid = fork();
        if ( ! pid ) {
                while(1) {
                        printf("%s%s%s\n", s, s, s);
                }
        } else {
                while (1) {
                        kill(pid, SIGHUP);
                }
        }
        return 0;
}

$ cc -W -Wall -pedantic -std=c99 1.c -o 1

$ ./1 >|logg

Ctrl-C
$ more logg
...
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
Hello, worldHello, worldFuck worldld
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
Fuck world
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
Hello, worldFuck world
Hello, worldHello, world
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
Fuck world
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
Fuck world
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
...
===}}}

Мало того, на солярке:

==={{{
$ more logg
...
Hello, worldHello, worldHello, woFuck world
rld
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
...
Hello, worldHello, worldHello, world
Hello, wFuck world
orldHello, worldHello, world
Hello, worldHello, worldHello, world
Hello, worldHello, worldHello, world
...
===}}}

Вообще этот спор о сортах говна поднадоел.
printf из обработчика сигнала делать нельзя. Period.
И вменяемые разработчики этому правилу следуют.

А что там в случае использования напечатается никому вобщем-то не интересно.

execve
()
Ответ на: комментарий от execve

> Вообще этот спор о сортах говна поднадоел.

А мне забавно пообсуждать никому не нужные вещи ;) Яж anonymous! :)

anonymous
()
Ответ на: комментарий от execve

> printf из обработчика сигнала делать нельзя. Period.

Это неправда. async-signal-unsafe функции можно вызывать из обработчика сигнала. Просто в этом случае их нельзя вызывать в основном теле программы.

Но зачем такое может понадобиться - ума не приложу ;)

anonymous
()
Ответ на: комментарий от anonymous

> Это неправда. async-signal-unsafe функции можно вызывать из обработчика сигнала. Просто в этом случае их нельзя вызывать в основном теле программы.

...а так же нельзя вызывать в основном теле программы все функции, которые в свою очередь вызываются небезопасным вызовом. у вас есть уверенность, что printf() ни при каких условиях не вызывает, скажем, malloc()? независимо от платформы? у меня вот нет такой уверенности бо быть её не может. нет, ну конечно, если вы не вызываете malloc() то без проблем :)

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda


ps: это я к тому, что утверждение "в обработчика сигнала *нельзя* вызывать printf()" верно без всяких "если". просто нельзя. c'est la vie.

// wbr

klalafuda ★☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.