eloop.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /** @file eloop.c
  2. * @brief Class for
  3. */
  4. #ifdef HAVE_CONFIG_H
  5. #include "config.h"
  6. #endif /* HAVE_CONFIG_H */
  7. #include <stdlib.h>
  8. #include <stdint.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <assert.h>
  12. #include <unistd.h>
  13. #include <errno.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #include <time.h>
  18. #include <signal.h>
  19. #include <poll.h>
  20. #include <sys/signalfd.h>
  21. #include "faux/faux.h"
  22. #include "faux/str.h"
  23. #include "faux/net.h"
  24. #include "faux/sched.h"
  25. #include "faux/eloop.h"
  26. #include "private.h"
  27. #ifdef HAVE_SIGNALFD
  28. #define SIGNALFD_FLAGS (SFD_NONBLOCK | SFD_CLOEXEC)
  29. #else // Standard signals
  30. static void *faux_eloop_static_user_data = NULL;
  31. static void faux_eloop_static_sighandler(int signo)
  32. {
  33. faux_list_t *signal_list =
  34. (faux_list_t *)faux_eloop_static_user_data;
  35. faux_eloop_signal_t *signal = NULL;
  36. if (!signal_list)
  37. return;
  38. signal = faux_list_kfind(signal_list, &signo);
  39. if (!signal)
  40. return;
  41. signal->set = BOOL_TRUE;
  42. }
  43. #endif
  44. static int faux_eloop_sched_compare(const void *first, const void *second)
  45. {
  46. const faux_eloop_sched_t *f = (const faux_eloop_sched_t *)first;
  47. const faux_eloop_sched_t *s = (const faux_eloop_sched_t *)second;
  48. return (f->ev_id - s->ev_id);
  49. }
  50. static int faux_eloop_sched_kcompare(const void *key, const void *list_item)
  51. {
  52. int *f = (int *)key;
  53. const faux_eloop_sched_t *s = (const faux_eloop_sched_t *)list_item;
  54. return (*f - s->ev_id);
  55. }
  56. static int faux_eloop_fd_compare(const void *first, const void *second)
  57. {
  58. const faux_eloop_fd_t *f = (const faux_eloop_fd_t *)first;
  59. const faux_eloop_fd_t *s = (const faux_eloop_fd_t *)second;
  60. return (f->fd - s->fd);
  61. }
  62. static int faux_eloop_fd_kcompare(const void *key, const void *list_item)
  63. {
  64. int *f = (int *)key;
  65. const faux_eloop_fd_t *s = (const faux_eloop_fd_t *)list_item;
  66. return (*f - s->fd);
  67. }
  68. static int faux_eloop_signal_compare(const void *first, const void *second)
  69. {
  70. const faux_eloop_signal_t *f = (const faux_eloop_signal_t *)first;
  71. const faux_eloop_signal_t *s = (const faux_eloop_signal_t *)second;
  72. return (f->signo - s->signo);
  73. }
  74. static int faux_eloop_signal_kcompare(const void *key, const void *list_item)
  75. {
  76. int *f = (int *)key;
  77. const faux_eloop_signal_t *s = (const faux_eloop_signal_t *)list_item;
  78. return (*f - s->signo);
  79. }
  80. faux_eloop_t *faux_eloop_new(faux_eloop_cb_f *default_event_cb)
  81. {
  82. faux_eloop_t *eloop = NULL;
  83. eloop = faux_zmalloc(sizeof(*eloop));
  84. assert(eloop);
  85. if (!eloop)
  86. return NULL;
  87. // Init
  88. eloop->working = BOOL_FALSE;
  89. eloop->default_event_cb = default_event_cb;
  90. // Sched
  91. eloop->scheds = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  92. faux_eloop_sched_compare, faux_eloop_sched_kcompare, faux_free);
  93. assert(eloop->scheds);
  94. eloop->faux_sched = faux_sched_new();
  95. assert(eloop->faux_sched);
  96. // FD
  97. eloop->fds = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  98. faux_eloop_fd_compare, faux_eloop_fd_kcompare, faux_free);
  99. assert(eloop->fds);
  100. eloop->pollfds = faux_pollfd_new();
  101. assert(eloop->pollfds);
  102. // Signal
  103. eloop->signals = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  104. faux_eloop_signal_compare, faux_eloop_signal_kcompare, faux_free);
  105. assert(eloop->signals);
  106. sigemptyset(&eloop->sig_set);
  107. sigfillset(&eloop->sig_mask);
  108. #ifdef HAVE_SIGNALFD
  109. eloop->signal_fd = -1;
  110. #endif
  111. return eloop;
  112. }
  113. void faux_eloop_free(faux_eloop_t *eloop)
  114. {
  115. if (!eloop)
  116. return;
  117. faux_list_free(eloop->signals);
  118. faux_pollfd_free(eloop->pollfds);
  119. faux_list_free(eloop->fds);
  120. faux_sched_free(eloop->faux_sched);
  121. faux_list_free(eloop->scheds);
  122. faux_free(eloop);
  123. }
  124. bool_t faux_eloop_loop(faux_eloop_t *eloop)
  125. {
  126. bool_t retval = BOOL_TRUE;
  127. bool_t stop = BOOL_FALSE;
  128. sigset_t blocked_signals;
  129. sigset_t orig_sig_set;
  130. sigset_t *sigset_for_ppoll = NULL;
  131. // If event loop is active already and we try to start nested loop
  132. // then return.
  133. if (eloop->working)
  134. return BOOL_FALSE;
  135. eloop->working = BOOL_TRUE;
  136. // Block signals to prevent race conditions while loop and ppoll()
  137. // Catch signals while ppoll() only
  138. sigfillset(&blocked_signals);
  139. sigprocmask(SIG_SETMASK, &blocked_signals, &orig_sig_set);
  140. #ifdef HAVE_SIGNALFD
  141. // Create Linux-specific signal file descriptor. Wait for all signals.
  142. // Unneeded signals will be filtered out later.
  143. eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
  144. SIGNALFD_FLAGS);
  145. faux_pollfd_add(eloop->pollfds, eloop->signal_fd, POLLIN);
  146. #else // Standard signal processing
  147. sigset_for_ppoll = &eloop->sig_mask;
  148. faux_eloop_static_user_data = eloop->signals;
  149. if (faux_list_len(eloop->signals) != 0) {
  150. faux_list_node_t *iter = faux_list_head(eloop->signals);
  151. faux_eloop_signal_t *sig = NULL;
  152. struct sigaction sig_act = {};
  153. sig_act.sa_flags = 0;
  154. sig_act.sa_mask = eloop->sig_set;
  155. sig_act.sa_handler = &faux_eloop_static_sighandler;
  156. while ((sig = (faux_eloop_signal_t *)faux_list_each(&iter))) {
  157. sig->set = BOOL_FALSE;
  158. sigaction(sig->signo, &sig_act, &sig->oldact);
  159. }
  160. }
  161. #endif
  162. // Main loop
  163. while (!stop) {
  164. int sn = 0;
  165. struct timespec *timeout = NULL;
  166. // struct timespec next_interval = {};
  167. faux_pollfd_iterator_t pollfd_iter;
  168. struct pollfd *pollfd = NULL;
  169. // Find out next scheduled interval
  170. /* if (faux_sched_next_interval(eloop->sched, &next_interval) < 0)
  171. timeout = NULL;
  172. else
  173. timeout = &next_interval;
  174. */
  175. // Wait for events
  176. sn = ppoll(faux_pollfd_vector(eloop->pollfds),
  177. faux_pollfd_len(eloop->pollfds), timeout, sigset_for_ppoll);
  178. if ((sn < 0) && (errno != EINTR)) {
  179. retval = BOOL_FALSE;
  180. break;
  181. }
  182. #ifndef HAVE_SIGNALFD // Standard signals
  183. // Signals
  184. if ((sn < 0) && (EINTR == errno)) {
  185. faux_list_node_t *iter = faux_list_head(eloop->signals);
  186. faux_eloop_signal_t *sig = NULL;
  187. while ((sig = (faux_eloop_signal_t *)faux_list_each(&iter))) {
  188. faux_eloop_info_signal_t sinfo = {};
  189. faux_eloop_cb_f *event_cb = NULL;
  190. bool_t r = BOOL_TRUE;
  191. if (BOOL_FALSE == sig->set)
  192. continue;
  193. sig->set = BOOL_FALSE;
  194. event_cb = sig->context.event_cb;
  195. if (!event_cb)
  196. event_cb = eloop->default_event_cb;
  197. if (!event_cb) // Callback is not defined
  198. continue;
  199. sinfo.signo = sig->signo;
  200. // Execute callback
  201. r = event_cb(eloop, FAUX_ELOOP_SIGNAL, &sinfo,
  202. sig->context.user_data);
  203. // BOOL_FALSE return value means "break the loop"
  204. if (!r)
  205. stop = BOOL_TRUE;
  206. }
  207. }
  208. #endif
  209. // Scheduled event
  210. if (0 == sn) {
  211. // int id = 0; // Event idenftifier
  212. // void *data = NULL; // Event data
  213. // faux_eloop_info_sched_t info = {};
  214. printf("Sheduled event\n");
  215. // Some scheduled events
  216. /* while(faux_sched_pop(sched, &id, &data) == 0) {
  217. syslog(LOG_DEBUG, "sched: Update event\n");
  218. }
  219. */ continue;
  220. }
  221. // File descriptor
  222. faux_pollfd_init_iterator(eloop->pollfds, &pollfd_iter);
  223. while ((pollfd = faux_pollfd_each_active(eloop->pollfds, &pollfd_iter))) {
  224. int fd = pollfd->fd;
  225. faux_eloop_info_fd_t info = {};
  226. faux_eloop_cb_f *event_cb = NULL;
  227. faux_eloop_fd_t *entry = NULL;
  228. bool_t r = BOOL_TRUE;
  229. #ifdef HAVE_SIGNALFD
  230. // Read special signal file descriptor
  231. if (fd == eloop->signal_fd) {
  232. struct signalfd_siginfo signal_info = {};
  233. while (faux_read_block(fd, &signal_info,
  234. sizeof(signal_info)) == sizeof(signal_info)) {
  235. faux_eloop_info_signal_t sinfo = {};
  236. faux_eloop_signal_t *sentry =
  237. (faux_eloop_signal_t *)faux_list_kfind(
  238. eloop->signals, &signal_info.ssi_signo);
  239. if (!sentry) // Not registered signal. Drop it.
  240. continue;
  241. event_cb = sentry->context.event_cb;
  242. if (!event_cb)
  243. event_cb = eloop->default_event_cb;
  244. if (!event_cb) // Callback is not defined
  245. continue;
  246. sinfo.signo = sentry->signo;
  247. // Execute callback
  248. r = event_cb(eloop, FAUX_ELOOP_SIGNAL, &sinfo,
  249. sentry->context.user_data);
  250. // BOOL_FALSE return value means "break the loop"
  251. if (!r)
  252. stop = BOOL_TRUE;
  253. }
  254. continue; // Another fds are common, not signal
  255. }
  256. #endif
  257. // Prepare event data
  258. entry = (faux_eloop_fd_t *)faux_list_kfind(eloop->fds, &fd);
  259. assert(entry);
  260. if (!entry) // Something went wrong
  261. continue;
  262. event_cb = entry->context.event_cb;
  263. if (!event_cb)
  264. event_cb = eloop->default_event_cb;
  265. if (!event_cb) // Callback function is not defined for this event
  266. continue;
  267. info.fd = fd;
  268. info.revents = pollfd->revents;
  269. // Execute callback
  270. r = event_cb(eloop, FAUX_ELOOP_FD, &info, entry->context.user_data);
  271. // BOOL_FALSE return value means "break the loop"
  272. if (!r)
  273. stop = BOOL_TRUE;
  274. }
  275. } // Loop end
  276. #ifdef HAVE_SIGNALFD
  277. // Close signal file descriptor
  278. faux_pollfd_del_by_fd(eloop->pollfds, eloop->signal_fd);
  279. close(eloop->signal_fd);
  280. eloop->signal_fd = -1;
  281. #else // Standard signals. Restore signal handlers
  282. if (faux_list_len(eloop->signals) != 0) {
  283. faux_list_node_t *iter = faux_list_head(eloop->signals);
  284. faux_eloop_signal_t *sig = NULL;
  285. while ((sig = (faux_eloop_signal_t *)faux_list_each(&iter))) {
  286. sig->set = BOOL_FALSE;
  287. sigaction(sig->signo, &sig->oldact, NULL);
  288. }
  289. }
  290. #endif
  291. // Unblock signals
  292. sigprocmask(SIG_SETMASK, &orig_sig_set, NULL);
  293. // Deactivate loop flag
  294. eloop->working = BOOL_FALSE;
  295. return retval;
  296. }
  297. bool_t faux_eloop_add_fd(faux_eloop_t *eloop, int fd, short events,
  298. faux_eloop_cb_f *event_cb, void *user_data)
  299. {
  300. faux_eloop_fd_t *entry = NULL;
  301. faux_list_node_t *new_node = NULL;
  302. if (!eloop || (fd < 0))
  303. return BOOL_FALSE;
  304. entry = faux_zmalloc(sizeof(*entry));
  305. if (!entry)
  306. return BOOL_FALSE;
  307. entry->fd = fd;
  308. entry->events = events;
  309. entry->context.event_cb = event_cb;
  310. entry->context.user_data = user_data;
  311. if (!(new_node = faux_list_add(eloop->fds, entry))) {
  312. faux_free(entry);
  313. return BOOL_FALSE;
  314. }
  315. if (!faux_pollfd_add(eloop->pollfds, entry->fd, entry->events)) {
  316. faux_list_del(eloop->fds, new_node);
  317. faux_free(entry);
  318. return BOOL_FALSE;
  319. }
  320. return BOOL_TRUE;
  321. }
  322. bool_t faux_eloop_del_fd(faux_eloop_t *eloop, int fd)
  323. {
  324. if (!eloop || (fd < 0))
  325. return BOOL_FALSE;
  326. if (faux_list_kdel(eloop->fds, &fd) < 0)
  327. return BOOL_FALSE;
  328. if (faux_pollfd_del_by_fd(eloop->pollfds, fd) < 0)
  329. return BOOL_FALSE;
  330. return BOOL_TRUE;
  331. }
  332. bool_t faux_eloop_add_signal(faux_eloop_t *eloop, int signo,
  333. faux_eloop_cb_f *event_cb, void *user_data)
  334. {
  335. faux_eloop_signal_t *entry = NULL;
  336. if (!eloop || (signo < 0))
  337. return BOOL_FALSE;
  338. if (sigismember(&eloop->sig_set, signo) == 1)
  339. return BOOL_FALSE; // Already exists
  340. // Firstly try to add signal to sigset. Library function will validate
  341. // signal number value.
  342. if (sigaddset(&eloop->sig_set, signo) < 0)
  343. return BOOL_FALSE; // Invalid signal number
  344. sigdelset(&eloop->sig_mask, signo);
  345. entry = faux_zmalloc(sizeof(*entry));
  346. if (!entry) {
  347. sigdelset(&eloop->sig_set, signo);
  348. sigaddset(&eloop->sig_mask, signo);
  349. return BOOL_FALSE;
  350. }
  351. entry->signo = signo;
  352. entry->set = BOOL_FALSE;
  353. entry->context.event_cb = event_cb;
  354. entry->context.user_data = user_data;
  355. if (!faux_list_add(eloop->signals, entry)) {
  356. faux_free(entry);
  357. sigdelset(&eloop->sig_set, signo);
  358. sigaddset(&eloop->sig_mask, signo);
  359. return BOOL_FALSE;
  360. }
  361. if (eloop->working) { // Add signal on the fly
  362. #ifdef HAVE_SIGNALFD
  363. // Reattach signalfd handler with updated sig_set
  364. eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
  365. SIGNALFD_FLAGS);
  366. #else // Standard signals
  367. struct sigaction sig_act = {};
  368. sig_act.sa_flags = 0;
  369. sig_act.sa_mask = eloop->sig_set;
  370. sig_act.sa_handler = &faux_eloop_static_sighandler;
  371. sigaction(signo, &sig_act, &entry->oldact);
  372. #endif
  373. }
  374. return BOOL_TRUE;
  375. }
  376. bool_t faux_eloop_del_signal(faux_eloop_t *eloop, int signo)
  377. {
  378. if (!eloop || (signo < 0))
  379. return BOOL_FALSE;
  380. if (sigismember(&eloop->sig_set, signo) != 1)
  381. return BOOL_FALSE; // Doesn't exist
  382. sigdelset(&eloop->sig_set, signo);
  383. sigaddset(&eloop->sig_mask, signo);
  384. if (eloop->working) { // Del signal on the fly
  385. #ifdef HAVE_SIGNALFD
  386. // Reattach signalfd handler with updated sig_set
  387. eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
  388. SIGNALFD_FLAGS);
  389. #else // Standard signals
  390. faux_eloop_signal_t *sig = faux_list_kfind(eloop->signals, &signo);
  391. sigaction(signo, &sig->oldact, NULL);
  392. #endif
  393. }
  394. faux_list_kdel(eloop->signals, &signo);
  395. return BOOL_TRUE;
  396. }