2013-04-19 1 views
0

Я хочу сделать пример приложения с libev. Я хочу иметь наблюдателя на вводе на клавиатуре, который будет анализировать несколько команд, таких как «start» «stop» «exit». В «start» я хочу создать канал и развернуть приложение, чтобы запустить какого-нибудь рабочего (например, ffmpeg с exec() или только некоторый цикл, который печатает некоторые символы) в дочернем элементе и установить наблюдателя на этом канале в родительском для вывода вывода на консоль , В команде «stop» я хочу убить ребенка и удалить наблюдателя.Ошибка сегментации в libev после fork

Я реализовал эту программу, но после развилки я всегда получаю segfault на ввод с клавиатуры, когда ребенок работает.

Сначала я подумал, что, если STDIN можно разделить между дочерним и родительским. Я пытался отделить ребенка, закрыть STDIN у ребенка. Затем я попробовал dupSTDIN и закрыл по умолчанию STDIN в исходном состоянии в начале и установил наблюдателя на дублированный STDIN. Я также попытался закрыть дескрипторы STDOUT/ERR перед разветвлением и восстановить их у родителя после вилки.

Я остановился и запустил user_input наблюдатель в user_input обратный вызов в случае, если это может вам помочь.

Затем я попытался выполнить ev_default_fork() и ev_loop_fork() у ребенка (это не нужно, потому что я хочу exec() только после развилки или в любом случае ребенок петля никогда не получить контроль) без успеха.

Я также пытался использовать разные задние части (select вместо epoll).

Также я попытался игнорировать некоторые сигналы, такие как SIGHUPSIGPIPESIGCHILD.

Я заметил также, что мой ввод после fork() вызывает segfault и bash, чтобы получить его как команду, поэтому, если я сделаю что-то вроде этого (с помощью «>» я обозначаю самописный ввод и с «<» программой и системой выход):

> $ ./libev_example 
> start 
< Debug: fork data got: 
< [Data got from child through pipe] 
> asd 
< Segmentation fault (core dumped) 
< $ asd 
< bash: asd: command not found... 

Тогда я построил libev из источников и пытался отладить. Происходит в выдаёт ошибку сегментации ev.c:1698

if (expect_false (w_->pending)) 
     pendings [pri][w_->pending - 1].events |= revents; 
    else 

значение pri является 4, и как я мог понять, что это приоритет. pendings[4] - 0x0, поэтому происходит segfault. Когда программа не сбой кода идет в else ветви.

Fd, что epoll возвращает 0, но я не использовал 0 в качестве fd в любом случае. Более того, для 0 есть наблюдатель в loop->anfds, который имеет обратный вызов моего обратного вызова user_input. В предыдущей итерации, когда я вводил какую-либо строку, не было никакого события для 0. Я проверил fds трубы, и они также имеют число терки, затем 0.

Я не могу понять, что происходит здесь и что я делаю неправильно. Я могу разместить здесь какой-то код, но там нет ничего особенного. Этот пост достаточно большой, поэтому, если кто-то запросит код, я отправлю его позже.

Спасибо.

ответ

0

Хорошо. Некоторое время с gdb решила проблему.Я обнаружил пару ошибок в моем коде, у которых нет прямой связи с libev или fork.

И проблема, вызвавшая такое странное поведение, была моей ошибкой, которую я не заметил из-за своей невнимательности. Я подклассы стандартной ev_io-структуры, но по какой-то причине я сделал это:

typedef struct lee_user_input_event_t{ 
    struct ev_io *event; 
    struct lee_process_data_t *child_process_data; 
... 
}; 

Вместо этого:

typedef struct lee_user_input_event_t{ 
    struct ev_io event; 
    struct lee_process_data_t *child_process_data; 
... 
} 

Так заливка указателя событий в обратном вызове для моей структуры был полной и огромной катастрофой.