libevent EVLOOP_NO_EXIT_ON_EMPTY not working? - c

I don't understand how the EVLOOP_NO_EXIT_ON_EMPTY flag is supposed to work in version 2.1.x of libevent.
If I don't add any events to my event_base the
event_base_loop(my_base, EVLOOP_NO_EXIT_ON_EMPTY);
call returns
immediately which is not at all what I think it's supposed to do.
If I add an event it loops with that pending event until it get's active but then the loop exits which I hoped would not happen.
Goal:
Have a named pipe open and libevent listening for a read.
Whenever I
echo "something" > pipe
the registered callback should be called. If the callback has finished the event get's back to pending and the loop waits for another echo.
Here's what I got so far: (error checking omitted)
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <event.h>
#include <unistd.h>
#define PIPE "/tmp/ev_pipe"
void cb_func(evutil_socket_t fd, short what, void *arg)
{
printf("foo\n");
}
int main(void)
{
/* create & open named pipe */
mkfifo(PIPE, 0666);
int socket = open(PIPE, O_RDONLY | O_NONBLOCK);
/* libevent specific stuff */
struct event_base *ev_base = event_base_new();
struct event *ev = event_new(ev_base, (evutil_socket_t) socket, EV_READ, cb_func, NULL);
event_add(ev, NULL);
/* loop forever */
event_base_loop(ev_base, EVLOOP_NO_EXIT_ON_EMPTY);
printf("a\n");
/* clean up */
unlink(PIPE);
event_base_free(ev_base);
close(socket);
return 0;
}
What am I missing? The event loop exits after the first write to the queue :/
Thanks for any help!

The implementation of the feature looks buggy! I had faced the same issue with the 2.1.x version. One way to get around the issue is as #Wizzard has pointed out. Another way of getting around the issue is OR the flag EV_PERSIST to the events argument to the function event_new:
struct event *ev = event_new(ev_base,
(evutil_socket_t) socket, EV_READ|EV_PERSIST, cb_func, NULL);
This will prevent the event from being removed. https://github.com/libevent/libevent/blob/master/include/event2/event.h +872
Please be aware that you might get multiple callbacks when there is data on pipe.

Just use event_base_dispatch (ev_base); instead of event_base_loop ()``, it will loop and handle all attached events either until you explicitly delete all attached events or callevent_base_loopbreak ()``` function.

Related

Is there a way to keep the program running while waiting for input?

We have an assignment to create a game in C. We can't use any external headers, and it should run on console.
I thought it would be cool to have animations going on. We already have a walking character and everything (printing matrix, updating, clearing screen, reprinting...), but it would be nice to have things such as running water, for example. To do that, I'd need a way to keep the program running while waiting for an input. As it currently is, the animations would stop as the user is prompted for an input (and he'll constantly be asked for directions), so it wouldn't work.
I'm wondering if there'd be a way to keep the animation running while the input prompt is still going, maybe having a timeout for the input function and re-prompting every frame until the user starts typing. We're familiar with C, but not with any of the obscure functions and headers that could be used to work around this problem.
How can I keep the program running while waiting for input?
You can use the select to monitor a file or a group of file descriptors until they have input available. Depending on the structure of your program you could also use asynchronous input where a callback is called when I/O is signaled as ready for a given file descriptor.
The rough snippet below shows the necessary methodology to allow for the callback action_handler to be called when input becomes available on the target file description, which emittes SIGIO. This allows for the input to be processed when it arrives, if it arrives. Using a socket (lets assume UDP) you would have something similar to the following.
#include <fcntl.h>
#include <signal.h>
#include <sys/socket.h>
...
create and bind socket
...
/** Set sigaction to use sigaction callback and not handler */
act.sa_flags = SA_SIGINFO; // Enables sigaction instead of handler
act.sa_sigaction = action_handler; // Callback function
/** Set mask to ignore all signals except SIGIO during execution of handler */
sigfillset(&act.sa_mask); // Mask all
sigdelset(&act.sa_mask, SIGIO); // Clear SIGIO from mask
/** Set callback for SIGIO */
sigaction(SIGIO, &act, NULL)
/** Set socket io signals to async and make sure SIGIO is sent to current
* process when a TCP connection is made on the socket
* */
file_status = fcntl(socket_fd, F_GETFL); // Get current status
file_status |= O_ASYNC | O_NONBLOCK;
fcntl(socket_fd, F_SETFL, file_status); // Set modified status flags
fcntl(socket_fd, F_SETSIG, SIGIO); // Produce a SIGIO signal when i/o is possible
fcntl(socket_fd, F_SETOWN, getpid()); // Make sure SIGIO signal is sent to current process
The easiest thing to do is just to change stdin over to non blocking. This is done (on Linux and others) by using the fcntl() function to change the F_SETFL option on stdin.
That will make fgetc() (or any other read) no longer block returning right away. If there wasn't any thing to read (no input) it will return an error. If there is something it will return that character.
Here is the call you need to make to change stdin to non-blocking.
fcntl(0, F_SETFL, FNDELAY);
The first argument is the file handle. We pass in 0 which is stdin. The next argument is the option we want to change (in this case F_SETFL), and the 3rd argument is what to change it to (FNDELAY is non-blocking mode).
Here is a simple example program:
#include <stdio.h>
#include <fcntl.h>
void SetupIO(void);
void ShutDownIO(void);
int main(void)
{
long count;
char c;
SetupIO();
count=0;
for(;;)
{
printf("Counting %d\r",count);
count++;
c=fgetc(stdin);
if(c=='q')
break;
}
ShutDownIO();
return 0;
}
void SetupIO(void)
{
fcntl(0, F_SETFL, FNDELAY);
}
void ShutDownIO(void)
{
fcntl(0, F_SETFL, 0);
}
This is great. It no longer blocks, but it still echos the characters being typed and you need to press enter before you will get back any input from fgetc().
If we want to make it more game like we need to tell the terminal to stop messing with our input. We need to switch the terminal into RAW mode.
The following example turn the terminal to RAW mode and changes stdin to non-blocking.
#include <termios.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
void SetupIO(void);
void ShutDownIO(void);
struct termios orig_termios;
int main(void)
{
long count;
char c;
SetupIO();
count=0;
for(;;)
{
printf("Counting %d\r",count);
count++;
c=fgetc(stdin);
if(c=='q')
break;
}
ShutDownIO();
return 0;
}
void SetupIO(void)
{
struct termios new_termios;
/* take two copies - one for now, one for later */
tcgetattr(0, &orig_termios);
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
/* register cleanup handler, and set the new terminal mode */
atexit(ShutDownIO);
cfmakeraw(&new_termios);
new_termios.c_iflag|=INLCR; // CR=NL
new_termios.c_lflag|=ISIG; // We still want Ctrl-C
tcsetattr(0, TCSANOW, &new_termios);
/* Non-blocking */
fcntl(0, F_SETFL, FNDELAY);
}
void ShutDownIO(void)
{
tcsetattr(0, TCSANOW, &orig_termios);
fcntl(0, F_SETFL, 0);
}
The downside to this is that if you Ctrl-C or your program crashes it will leave your terminal in a messed up state that is not easy to get back out of. You can help with this by adding an atexit() and/or signal handling.

Readline C: force return of certain text in readline()

I am trying to allow an interrupt to cause a certain value to be returned by readline. Here is a minimal example:
#include <stdio.h>
#include <signal.h>
#include <readline/readline.h>
void handler (int status)
{
rl_replace_line("word",0);
rl_redisplay();
rl_done = 1;
}
int main (int argc, char** argv)
{
char* entry;
signal(SIGINT,handler);
entry = readline("");
printf("\nEntry was: %s\n", entry);
return 0;
}
If I run this code and press Control-C, after I hit ENTER, sure enough it prints "Entry was: word". But I would like it to do so without the user needing to press ENTER. I basically just want to set entry to "word" when the interrupt signal is received, ending the readline function. I have been unable to find any documentation for how to just end the readline loop and return a certain value (I'm sure it's out there, but I haven't found it).
One thing I tried was adding
(*rl_named_function("accept-line"))(1,0);
at the end of handler, but it didn't send the text to "entry" immediately.
I think I have what you want running here.
#include <stdio.h>
#include <signal.h>
#include <readline/readline.h>
int event(void) { }
void handler (int status)
{
rl_replace_line("word",0);
rl_redisplay();
rl_done = 1;
}
int main (int argc, char** argv)
{
char* entry;
rl_event_hook=event;
signal(SIGINT,handler);
entry = readline("");
printf("\nEntry was: %s\n", entry);
return 0;
}
The secret is the rl_done is only checked in the event loop. When you give it a null event hook function, it checks the rl_done and exits.
I don't believe there is any guarantee that you can call back into readline functions from an asynchronous signal handler. (The fact that it "seems to" work does not guarantee that it will not fail disastrously from time to time.) In general, you should do the absolute minimum in a signal handler, such as setting a flag to indicate that the signal has been received.
The readline library provides the variable rl_signal_event_hook, whose value is a function which will be called when a readline call is interrupted by a signal. It would probably be wise to put any code which modifies the readline state into such a function.
But it seems like the safest solution here would be to arrange for the Control-C character to be passed directly to readline without triggering a SIGINT. You could create a custom terminal setting based on the termios struct returned by tcgetattr which turns off the mapping of Ctrl-C to the INTR function, either by unsetting the ISIG flag (which will also turn off other interrupt characters, including Ctrl-Z) or by changing c_cc[VINTR] to _POSIX_VDISABLE (or to some other key).
If you are on Windows and you are not using Cygwin, which includes termios emulation, you can use native APIs to enable and disable Control-C handling.
Then you can use rl_bind_key to bind Ctrl-C (which is 3) to your own function. The function needs to match the rl_command_func_t typedef, which is int(*)(int, int). The function should return 0; in your simple case, you can probably ignore the arguments, but for the record the first one is a "count" (the numeric argument, entered by typing a number while holding down the Alt key), and the second one is the key itself.
You should probably make a copy of the termios structure before you modify it so that you can reset the terminal settings once you're done. Generally, you would want to install and restore the terminal settings around every call to readline (which is what readline itself does, as well).
CTRL+C should pass a SIGINT, or similar interrupt signal to your program. There should be ways to override the handling, see here for example.
You can achieve this by using the alternate interface, where your code is doing the event loop and calls libreadline functions each time a character needs to be read from the terminal. In the event loop you can handle all extra asynchronous events like signals (but not only that --- think a terminal chat application where messages arrive asynchronously from the network).
Here's how it could look like:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <readline/readline.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
static volatile sig_atomic_t my_signal_flag = 0;
static int done_loop = 0;
void my_signal_handler (int status)
{
my_signal_flag = 1; // set a volaatile sig-atomic_t var
// and exit, just as the standard says
}
void my_rlhandler(char* line) // all your app is in this function
// called each time a line is ready
{
if (line && strcmp(line, "quit"))
printf("Entry was: %s\n", line);
else
{
done_loop = 1;
rl_set_prompt("");
}
free(line);
}
void my_event_loop() // event loop
// handle all async events here
// signals, network, threads, whatever
{
rl_callback_handler_install("w00t>", my_rlhandler);
do
{
signal(SIGINT, my_signal_handler); // readline may override this
// better do it here each time
fd_set readfds; // prepare the select
FD_ZERO(&readfds);
FD_SET(0, &readfds);
if (select(1, &readfds, NULL, NULL, NULL) > 0)
{
rl_callback_read_char(); // character ready, let readline eat it
}
else if (my_signal_flag )
{
my_signal_flag = 0; // can get here only after a signal
rl_replace_line("word",0);
rl_done = 1;
rl_redisplay();
rl_pending_input = '\n'; // not sure why it's needed
rl_callback_read_char();
}
}
while (!done_loop);
rl_callback_handler_remove();
}
int main (int argc, char** argv)
{
char* entry;
signal(SIGINT, my_signal_handler);
my_event_loop();
return 0;
}
While this may seem more complicated that other methods, the callback interface is more appropriate for real-life programs that need to handle a variety of events.

How to wait for time to expire

I would like to have a function run periodically, given a time step. What is the most efficient way to do this?
I know I could use a while look and just keep checking till the dt period has elapsed. But I'd like to know if there is a better, more efficient/elegant function to use.
I was looking into virtual timers and sigaction. Using this method, I would have the sigaction handler set a flag when the time has elapsed, but I would still need to sit in a while loop checking for that flag to be set in my main function. Alternatively I wonder if I could actually have the handler run the function, but then I would have to pass a lot of arguments, and as far as I have read, handlers don't take arguments, so I would have to use lots of global variables.
What would be the best way to tackled this?
On an *IX'ish system you could
install a handler for SIGALRM, which does nothing
set an alarm using alarm()
call blocking pause()
If the alarm signal is sent pause() will return and
you can run the function in question,
again set the alarm
start over calling pause()
#define _POSIX_SOURCE 1
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
void handler_SIGALRM(int signo)
{
signo = 0; /* Get rid of warning "unused parameter ‘signo’" (in a portable way). */
/* Do nothing. */
}
int main()
{
/* Override SIGALRM's default handler, as the default handler might end the program. */
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handler_SIGALRM;
if (-1 == sigaction(SIGALRM, &sa, NULL ))
{
perror("sigaction() failed");
exit(EXIT_FAILURE);
}
}
while (1)
{
alarm(2); /* Set alarm to occur in two seconds. */
pause(); /* The call blocks until a signal is received; in theis case typically SIGARLM. */
/* Do what is to be done every 2 seconds. */
}
return EXIT_SUCCESS;
}
The easiest way is to use sleep or usleep as defined in unistd.h.
If neither of those are available then a common workaround is to use a select with a timeout on no file descriptors.
Include time.h and use sleep function like
#include <time.h>
#include <stdio.h>
#include<windows.h>
#include <conio.h>
int main() {
printf("I am going to wait for 4 sec");
Sleep(4000); //sleep for 4000 microsecond= 4 second
printf("Finaaly the wait is over");
getch();
return 0;
}
It will give you a precise delay on microsecond level.
Hope it helped.

Why waiting indefinitely - timerfd_create? Where have i gone wrong?

I have created a timer which can expire, in 5 seconds using timerfd_create, but i can see that it is waiting indefinitely.
Can someone help me?
Thanks in advance.
Here is my code:
enter code here
#include <sys/timerfd.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <time.h>
int main()
{
struct itimerspec its;
struct epoll_event event, revent;
int timer_fd, efd;
/* Setting timer interval */
its.it_interval.tv_sec=1;
its.it_interval.tv_nsec=0;
/* Setting timer expiration */
its.it_value.tv_sec=5;
its.it_value.tv_nsec=0;
efd=epoll_create(2);
event.data.fd=timer_fd;
event.events=EPOLLIN;
epoll_ctl(efd, EPOLL_CTL_ADD, timer_fd, &event);
timer_fd=timerfd_create(CLOCK_REALTIME, 0);
if(timer_fd==-1)
{
perror("timerfd:");
}
if(timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &its, NULL)==-1)
{
perror("timerfd_settime error:");
}
printf("Starting the timer...");
while(1) {
epoll_wait(efd, &revent, 1, -1);
}
}
Reverse the order of calls to epoll_ctl and timerfd_create. Right now you are adding some random integer value to the event set.
Edit 0:
Several points:
timerfd_create(2) produces a file descriptor, just like open(2) or socket(2). You have to assign the return value to the timer_fd variable before giving it to the epoll_ctl(2), otherwise it's just a random integer value from the stack.
Don't use TFD_TIMER_ABSTIME - you are asking the kernel to start a timer that expires one second after the Epoch (which is not that big of a deal - it'll just expire immediately).
When the timer expires epoll_wait(2) returns the number of ready file descriptors, 1 in your example, and you are expected to handle that. You, on the other hand, just ignore that return value and spin around in a tight loop, so you don't even know the timer is expiring.
You need to read from timer file descriptor to consume the expiration event. Otherwise all subsequent calls to epoll_wait(2) will just return immediately since the descriptor remains in the "signaled" state.
Always check the return values of the system calls and handle error conditions based on the value of errno(3) - manual page for each call gives you possible error values.
Edit 1:
You do want a loop around the epoll_wait(2) (or select(2). or poll(2)), but you need:
handle the IO events being signaled (that's the whole point of these multiplexing APIs - being able to wait on multiple descriptors and dispatch the events), and
be able to break out of that loop (on a signal, on input from a dedicated file descriptor ala self-pipe trick, or on some application event).
Hope this helps.

UNIX/Linux signal handling: SIGEV_THREAD

I have put a simple signal handler in my code. I have initialised the sigevent structure, with a handler function to catch the signal.
Can someone please pin-point as to why the code is not working? Ideally if there is a signal, my handler should be called. But it is not.
Please help me,
Thanks
Kingsmasher1
enter code here
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
void my_handler(int sival_int, void* sival_ptr)
{
printf("my_handler caught\n");
signal(sig,my_handler);
}
int main()
{
struct sigevent sevp;
sevp.sigev_notify=SIGEV_THREAD;
sevp.sigev_signo=SIGRTMIN;
sevp.sigev_value.sival_ptr=NULL;
sevp.sigev_notify_function=(void*)my_handler;
kill(0,SIGRTMIN); // This should invoke the signal and call the function
}
struct sigevent is not about specifying how the process will handle a signal - struct sigaction and sigaction() are how you do that. Instead, struct sigevent is used to specify how your process will be informed of some asychronous event - like the completion of asychronous IO, or a timer expiring.
The sigev_notify field specifies how the event should be notified:
SIGEV_NONE - no notification at all. The remainder of the fields are ignored.
SIGEV_SIGNAL - a signal is sent to the process. The sigev_signo field specifies the signal, the sigev_value field contains supplementary data that is passed to the signal handling function, and the remainder of the fields are ignored.
SIGEV_THREAD - a function is called in a new thread. The sigev_notify_function field specifies the function that is called, sigev_value contains supplementary data that is passed to the function, and sigev_notify_attributes specifies thread attributes to use for the thread creation. The remainder of the fields are ignored.
Note in particular that if you set SIGEV_THREAD, the sigev_signo field is ignored - the struct sigevent is about specifying either a thread or a signal as a notification method, not about specifying a thread as the way that a signal should be handled.
The struct sigevent must also be passed to a function - like timer_create() - that sets up the asychronous event that will be notified. Simply creating a struct sigevent object does not do anything special.
If you wish to use a dedicated thread to handle a signal, create the thread up front and have it loop around, blocking on sigwaitinfo(). Use sigprocmask() to block the signal in every other thread.
I think you are mixing up your signal handling idioms here, you create a sigevent structure and then do nothing with it and then use signal() within the signal handler. The following code shows a very simple signal handling routine based on your code; note that I have changed the definition of my_handler. If you need more sophisticated handling then sigaction() is probably the system call you need to look into.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
void my_handler(int sig)
{
printf("my_handler caught\n");
signal(sig,my_handler);
}
int main()
{
signal(SIGRTMIN,my_handler);
kill(0,SIGRTMIN); // This should invoke the signal and call the function
while(1) ; // Infinite loop in case the program ends before the signal gets caught!
}
This works under cygwin on my windows box (no access to a linux box at the minute).
I hope this works.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
void
my_handler (int sig)
{
printf ("my_handler caught\n");
signal (sig, my_handler);
}
int
main ()
{
int signo;
struct sigevent sevp;
sigset_t set;
if (sigemptyset (&set) == -1)
perror ("sigemptyset");
if (sigaddset (&set, SIGRTMIN) == -1)
perror ("sigaddset");
if (sigprocmask (SIG_BLOCK, &set, NULL) == -1)
perror ("sigprocmask");
sevp.sigev_notify = SIGEV_THREAD;
sevp.sigev_signo = SIGRTMIN;
sevp.sigev_value.sival_ptr = NULL;
kill (0, SIGRTMIN);
if (sigwait (&set, &signo) == 0)
my_handler (signo);
else
perror ("sigwait");
}

Resources