Поведение, о котором вы сообщаете, согласуется с параметром IDE Code :: Blocks, явным или неявным образом, поведением SIGPIPE для SIG_IGN.Это легко унаследовано.Это не то, что я ожидал - я ожидал, что ваша программа будет запущена с SIGPIPE (и, действительно, со всеми другими сигналами), установленным в SIG_DFL, поведение сигнала по умолчанию.Если это окажется проблемой, у вас есть основание для сообщения об ошибке разработчикам Code :: Blocks.Если окажется, что проблема не в этом, тогда у нас есть некоторые серьезные размышления, чтобы решить, что на самом деле происходит *
.
Вы могли быпродемонстрируйте, происходит ли это с Code :: Blocks, обращая внимание на возвращаемое значение из signal()
или используя sigaction()
для опроса режима обработки сигналов без его изменения.
Например:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#define READING 0
#define WRITING 1
#define DESCRIPTOR_COUNT 2
static void signal_handler(int signum)
{
// Lazy; normally, I'd format the signal number into the string, carefully
(void)signum;
write(STDOUT_FILENO, "sigpipe received\n", sizeof("sigpipe received\n")-1);
}
int main(void)
{
void (*handler)(int) = signal(SIGPIPE, signal_handler);
if (handler == SIG_DFL)
printf("old handler was SIG_DFL\n");
else if (handler == SIG_IGN)
{
printf("old handler was SIG_IGN\n");
(void)signal(SIGPIPE, SIG_IGN);
}
else
{
// Standard C does not allow a cast from function pointer to object pointer
//printf("there was a non-standard handler installed (%p)\n", (void *)handler);
printf("there was a non-standard handler installed\n");
}
int tube[DESCRIPTOR_COUNT];
pipe(tube);
close(tube[READING]);
if (write(tube[WRITING], "message", 8) < 0)
{
if (errno == EPIPE)
printf("EPIPE returned\n");
else
printf("errno = %d\n", errno);
}
printf("123\n");
return EXIT_SUCCESS;
}
Обратите внимание, что стандартная идиома для настройки обработчика сигнала с помощью signal()
в программе была:
if (signal(signum, SIG_IGN) != SIG_IGN)
signal(signum, signal_handler);
Это означает, чтоесли программа была защищена от сигналов, она остается защищенной.Если он обрабатывал сигналы (по умолчанию или, возможно, явно при предварительном вызове signal()
), то вы устанавливаете свой собственный обработчик сигналов.Эквивалентный код с использованием sigaction()
будет иметь вид:
struct sigaction sa;
if (sigaction(signum, 0, &sa) == 0 && sa.sa_handler != SIG_IGN)
{
sa.sa_handler = signal_handler;
sa.sa_flag &= ~SA_SIGINFO;
sigaction(signum, sa, 0);
}
(Одно из преимуществ этого: структура инициализируется вызовом sigaction()
, поэтому нет необходимости возиться с масками.flags обеспечивает использование основного обработчика, а не расширенного обработчика.)
Когда я компилирую исходный код (pipe13.c
) в программу pipe13
и запускаю его, я получаю:
$ make pipe13
gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes pipe13.c -o pipe13
$ pipe13
old handler was SIG_DFL
sigpipe received
EPIPE returned
123
$ (trap '' 13; pipe13)
old handler was SIG_IGN
EPIPE returned
123
$
Этот вариант использует sigaction()
для опроса обработки сигнала:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#define READING 0
#define WRITING 1
#define DESCRIPTOR_COUNT 2
int main(void)
{
struct sigaction sa;
if (sigaction(SIGPIPE, 0, &sa) != 0)
fprintf(stderr, "siagaction() failed\n");
else if (sa.sa_handler == SIG_DFL)
printf("old handler was SIG_DFL\n");
else if (sa.sa_handler == SIG_IGN)
printf("old handler was SIG_IGN\n");
else
printf("there was a non-standard handler installed\n");
int tube[DESCRIPTOR_COUNT];
pipe(tube);
close(tube[READING]);
if (write(tube[WRITING], "message", 8) < 0)
{
if (errno == EPIPE)
printf("EPIPE returned\n");
else
printf("errno = %d\n", errno);
}
printf("123\n");
return EXIT_SUCCESS;
}
При запуске (программа pipe83
) я получаю:
$ pipe83
old handler was SIG_DFL
$ echo $?
141
$ (trap '' 13; pipe83)
old handler was SIG_IGN
EPIPE returned
123
$
Обратите внимание, что собработка сигналов по умолчанию, программа останавливается перед печатью 123
.Оболочки POSIX кодируют «ребенок умер от сигнала N», сообщая о состоянии выхода как 128 + N
;SIGPIPE равен 13
, поэтому 141
указывает, что оболочка умерла от сигнала SIGPIPE.(Да, современные молодые люди, вероятно, написали бы (trap '' PIPE; pipe83)
, и это работает - такие тонкости были недоступны, когда я изучал программирование оболочки.)
Было бы не так сложно обобщить код, чтобы проверить, является ли Код:: Blocks устанавливает любые другие сигналы, отличные от обработки по умолчанию.Тем не менее, это может быть немного неудобно, если вы хотите приспособиться к тому, какие сигналы доступны на машине.
*
In chat , мы установили, что программа запускается в образе VMware под управлением Fedora 28, размещенном на компьютере с Windows 10.Из-за этого существует достаточно возможных мест для возникновения проблем, так что не ясно, что проблема обязательно в Code :: Blocks - просто не ясно, откуда возникла проблема.Однако проблема действительно заключается в том, что тестовая программа запускается с обработкой SIGPIPE, установленной на SIG_IGN вместо SIG_DFL, когда она запускается из Code :: Blocks.