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.

Était-ce utile?

La 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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top