/*
- * ion/libmainloop/mainloop.c
+ * libmainloop/select.c
*
* Partly based on a contributed code.
*
- * Ion is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
+ * See the included file LICENSE for details.
*/
+#include <signal.h>
+#include <sys/select.h>
+#include <errno.h>
+
#include <libtu/types.h>
#include <libtu/misc.h>
#include <libtu/dlist.h>
#include "select.h"
+#include "signal.h"
/*{{{ File descriptor management */
{
fd_set rfds;
int nfds=0;
-
- FD_ZERO(&rfds);
+ int ret=0;
- set_input_fds(&rfds, &nfds);
- if(select(nfds+1, &rfds, NULL, NULL, NULL)>0)
+#ifdef _POSIX_SELECT
+ {
+ sigset_t oldmask;
+
+ FD_ZERO(&rfds);
+ set_input_fds(&rfds, &nfds);
+
+ mainloop_block_signals(&oldmask);
+
+ if(!mainloop_unhandled_signals())
+ ret=pselect(nfds+1, &rfds, NULL, NULL, NULL, &oldmask);
+
+ sigprocmask(SIG_SETMASK, &oldmask, NULL);
+ }
+#else
+ #warning "pselect() unavailable -- using dirty hacks"
+ {
+ struct timeval tv={0, 0};
+
+ /* If there are timers, make sure we return from select with
+ * some delay, if the timer signal happens right before
+ * entering select(). Race conditions with other signals
+ * we'll just have to ignore without pselect().
+ */
+ do{
+ FD_ZERO(&rfds);
+ set_input_fds(&rfds, &nfds);
+
+ bool to=libmainloop_get_timeout(&tv);
+
+ if(mainloop_unhandled_signals()){
+ ret=0;
+ break;
+ }
+
+ ret=select(nfds+1, &rfds, NULL, NULL, to ? &tv : NULL);
+ }while(ret<0 && errno==EINTR && !mainloop_unhandled_signals());
+ }
+#endif
+ if(ret>0)
check_input_fds(&rfds);
}