Question

I want to make an example application with libev. I want to have a watcher on keyboard input that will parse several commands like "start" "stop" "exit". On "start" I want to create a pipe and fork the application to start some worker(like ffmpeg with exec() or just some loop that prints some characters) in a child and set a watcher on this pipe in a parent to print output to console. On "stop" command I want to kill a child and remove a watcher.

I have implemented this program but after the fork I always get segfault on keyboard input when the child is running.

At first I thought that because if STDIN can be shared between child and parent. I've tried to detach child, close STDIN in child. Then I tried dup STDIN and close the default STDIN in parent at the beginning and set a watcher on duplicated STDIN. I also tried to close STDOUT/ERR descriptors before forking and restore them in the parent after the fork.

I stopped and start user_input watcher in user_input callback in case this could help.

Then I tried to execute ev_default_fork() and ev_loop_fork() in a child (this is not necessary because I want to exec() just after the fork or in any case the child loop never get a control) with no success.

I also tried to use different back-ends (select instead of epoll).

Also I tried to ignore some signals like SIGHUP SIGPIPE SIGCHILD.

I noticed also that my input after the fork() causes segfault and bash get it as a command so if I do something like this (With ">" I denote self-hand written input and with "<" the program and system output):

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

Then I built libev from sources and tried to debug. The segfault happens in ev.c:1698

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

the pri value is 4 and as I could understand it's a priority. pendings[4] is 0x0 so the segfault happens. When program doesn't crash code goes in else branch.

The fd that epoll returns is 0, but I didn't use 0 as fd in any event. Moreover for 0 there is a watcher in loop->anfds that has a callback to my user_input callback. In previous iteration, when I enter any string there was no event for 0. I checked the pipe fds and they are also have a number grater then 0.

I can't figure whats happen here and what I'm doing wrong. I can place here some code, but there is nothing special there. This post is quite big enough so if someone asks for the code I'll post it later.

Thanks.

Was it helpful?

Solution

Ok. Some time with gdb solved the problem. I found couple of errors in my code that has no straight connection with libev or fork.

And the problem that caused such strange behavior was my mistype that I didn't noticed due my inattention. I subclass the standard ev_io struct but for some reason I made this:

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

Instead of this:

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

So casting the event pointer in callback to my own struct was a complete and huge disaster.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top