eloop.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  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. #define TIMESPEC_TO_MILISECONDS(t) ((t.tv_sec * 1000) + (t.tv_nsec / 1000000l))
  28. #ifdef HAVE_SIGNALFD
  29. #define SIGNALFD_FLAGS (SFD_NONBLOCK | SFD_CLOEXEC)
  30. #else // Standard signals
  31. static void *faux_eloop_static_user_data = NULL;
  32. static void faux_eloop_static_sighandler(int signo)
  33. {
  34. int pipe = -1;
  35. if (!faux_eloop_static_user_data)
  36. return;
  37. pipe = *((int *)faux_eloop_static_user_data);
  38. write(pipe, &signo, sizeof(signo));
  39. }
  40. #endif
  41. static int faux_eloop_fd_compare(const void *first, const void *second)
  42. {
  43. const faux_eloop_fd_t *f = (const faux_eloop_fd_t *)first;
  44. const faux_eloop_fd_t *s = (const faux_eloop_fd_t *)second;
  45. return (f->fd - s->fd);
  46. }
  47. static int faux_eloop_fd_kcompare(const void *key, const void *list_item)
  48. {
  49. int *f = (int *)key;
  50. const faux_eloop_fd_t *s = (const faux_eloop_fd_t *)list_item;
  51. return (*f - s->fd);
  52. }
  53. static int faux_eloop_signal_compare(const void *first, const void *second)
  54. {
  55. const faux_eloop_signal_t *f = (const faux_eloop_signal_t *)first;
  56. const faux_eloop_signal_t *s = (const faux_eloop_signal_t *)second;
  57. return (f->signo - s->signo);
  58. }
  59. static int faux_eloop_signal_kcompare(const void *key, const void *list_item)
  60. {
  61. int *f = (int *)key;
  62. const faux_eloop_signal_t *s = (const faux_eloop_signal_t *)list_item;
  63. return (*f - s->signo);
  64. }
  65. faux_eloop_t *faux_eloop_new(faux_eloop_cb_f default_event_cb)
  66. {
  67. faux_eloop_t *eloop = NULL;
  68. eloop = faux_zmalloc(sizeof(*eloop));
  69. assert(eloop);
  70. if (!eloop)
  71. return NULL;
  72. // Init
  73. eloop->working = BOOL_FALSE;
  74. eloop->default_event_cb = default_event_cb;
  75. // Sched
  76. eloop->sched = faux_sched_new();
  77. assert(eloop->sched);
  78. // FD
  79. eloop->fds = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  80. faux_eloop_fd_compare, faux_eloop_fd_kcompare, faux_free);
  81. assert(eloop->fds);
  82. eloop->pollfds = faux_pollfd_new();
  83. assert(eloop->pollfds);
  84. // Signal
  85. eloop->signals = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  86. faux_eloop_signal_compare, faux_eloop_signal_kcompare, faux_free);
  87. assert(eloop->signals);
  88. sigemptyset(&eloop->sig_set);
  89. sigfillset(&eloop->sig_mask);
  90. #ifdef HAVE_SIGNALFD
  91. eloop->signal_fd = -1;
  92. #endif
  93. return eloop;
  94. }
  95. void faux_eloop_free(faux_eloop_t *eloop)
  96. {
  97. if (!eloop)
  98. return;
  99. faux_list_free(eloop->signals);
  100. faux_pollfd_free(eloop->pollfds);
  101. faux_list_free(eloop->fds);
  102. faux_sched_free(eloop->sched);
  103. faux_free(eloop);
  104. }
  105. bool_t faux_eloop_loop(faux_eloop_t *eloop)
  106. {
  107. bool_t retval = BOOL_TRUE;
  108. bool_t stop = BOOL_FALSE;
  109. sigset_t blocked_signals;
  110. sigset_t orig_sig_set;
  111. #ifdef HAVE_PPOLL
  112. sigset_t *sigset_for_ppoll = NULL;
  113. #endif // HAVE_PPOLL
  114. #ifndef HAVE_SIGNALFD
  115. int signal_pipe[2];
  116. int fflags = 0;
  117. #endif // not HAVE_SIGNALFD
  118. // If event loop is active already and we try to start nested loop
  119. // then return.
  120. if (eloop->working)
  121. return BOOL_FALSE;
  122. eloop->working = BOOL_TRUE;
  123. // Block signals to prevent race conditions while loop and ppoll()
  124. // Catch signals while ppoll() only
  125. sigfillset(&blocked_signals);
  126. sigprocmask(SIG_SETMASK, &blocked_signals, &orig_sig_set);
  127. #ifdef HAVE_SIGNALFD
  128. // Create Linux-specific signal file descriptor. Wait for signals.
  129. eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
  130. SIGNALFD_FLAGS);
  131. faux_pollfd_add(eloop->pollfds, eloop->signal_fd, POLLIN);
  132. #else // Standard signal processing
  133. #ifdef PPOLL
  134. sigset_for_ppoll = &eloop->sig_mask;
  135. #endif // HAVE_PPOLL
  136. // Create signal pipe pair to get signal number on pipe read end
  137. pipe(signal_pipe);
  138. fcntl(signal_pipe[0], F_SETFD, FD_CLOEXEC);
  139. fflags = fcntl(signal_pipe[0], F_GETFL);
  140. fcntl(signal_pipe[0], F_SETFL, fflags | O_NONBLOCK);
  141. fcntl(signal_pipe[1], F_SETFD, FD_CLOEXEC);
  142. fflags = fcntl(signal_pipe[1], F_GETFL);
  143. fcntl(signal_pipe[1], F_SETFL, fflags | O_NONBLOCK);
  144. faux_eloop_static_user_data = &signal_pipe[1];
  145. faux_pollfd_add(eloop->pollfds, signal_pipe[0], POLLIN);
  146. if (faux_list_len(eloop->signals) != 0) {
  147. faux_list_node_t *iter = faux_list_head(eloop->signals);
  148. faux_eloop_signal_t *sig = NULL;
  149. struct sigaction sig_act = {};
  150. sig_act.sa_flags = 0;
  151. sig_act.sa_mask = eloop->sig_set;
  152. sig_act.sa_handler = &faux_eloop_static_sighandler;
  153. while ((sig = (faux_eloop_signal_t *)faux_list_each(&iter)))
  154. sigaction(sig->signo, &sig_act, &sig->oldact);
  155. }
  156. #endif // HAVE_SIGNALFD
  157. // Main loop
  158. while (!stop) {
  159. int sn = 0;
  160. struct timespec *timeout = NULL;
  161. struct timespec next_interval = {};
  162. faux_pollfd_iterator_t pollfd_iter;
  163. struct pollfd *pollfd = NULL;
  164. // Find out next scheduled interval
  165. if (!faux_sched_next_interval(eloop->sched, &next_interval))
  166. timeout = NULL;
  167. else
  168. timeout = &next_interval;
  169. // Wait for events
  170. #ifdef HAVE_PPOLL
  171. sn = ppoll(faux_pollfd_vector(eloop->pollfds),
  172. faux_pollfd_len(eloop->pollfds), timeout, sigset_for_ppoll);
  173. #else // poll()
  174. sigprocmask(SIG_SETMASK, &eloop->sig_mask, NULL);
  175. sn = poll(faux_pollfd_vector(eloop->pollfds),
  176. faux_pollfd_len(eloop->pollfds),
  177. timeout ? TIMESPEC_TO_MILISECONDS(next_interval) : -1);
  178. sigprocmask(SIG_SETMASK, &blocked_signals, NULL);
  179. #endif // HAVE_PPOLL
  180. // Error or signal
  181. if (sn < 0) {
  182. // Let poll() read signal pipe or signalfd on next step
  183. if (EINTR == errno)
  184. continue;
  185. retval = BOOL_FALSE;
  186. break;
  187. }
  188. // Scheduled event
  189. if (0 == sn) {
  190. faux_ev_t *ev = NULL;
  191. // Some scheduled events
  192. while((ev = faux_sched_pop(eloop->sched))) {
  193. faux_eloop_info_sched_t info = {};
  194. bool_t r = BOOL_TRUE;
  195. int ev_id = faux_ev_id(ev);
  196. faux_eloop_context_t *context =
  197. (faux_eloop_context_t *)faux_ev_data(ev);
  198. faux_eloop_cb_f event_cb = context->event_cb;
  199. void *user_data = context->user_data;
  200. if (!faux_ev_is_busy(ev)) {
  201. faux_ev_free(ev);
  202. ev = NULL;
  203. }
  204. if (!event_cb)
  205. event_cb = eloop->default_event_cb;
  206. if (!event_cb) // Callback is not defined
  207. continue;
  208. info.ev_id = ev_id;
  209. // Callback will get only rescheduled event object.
  210. // If event is not scheduled, callback will get NULL.
  211. info.ev = ev;
  212. // Execute callback
  213. r = event_cb(eloop, FAUX_ELOOP_SCHED, &info,
  214. user_data);
  215. // BOOL_FALSE return value means "break the loop"
  216. if (!r)
  217. stop = BOOL_TRUE;
  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. // Read special signal file descriptor
  230. #ifdef HAVE_SIGNALFD
  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. int signo = signal_info.ssi_signo;
  236. #else
  237. if (fd == signal_pipe[0]) {
  238. int tmp = 0;
  239. while (faux_read_block(fd, &tmp,
  240. sizeof(tmp)) == sizeof(tmp)) {
  241. int signo = tmp;
  242. #endif // HAVE_SIGNALFD
  243. faux_eloop_info_signal_t sinfo = {};
  244. faux_eloop_signal_t *sentry =
  245. (faux_eloop_signal_t *)faux_list_kfind(
  246. eloop->signals, &signo);
  247. if (!sentry) // Not registered signal. Drop it.
  248. continue;
  249. event_cb = sentry->context.event_cb;
  250. if (!event_cb)
  251. event_cb = eloop->default_event_cb;
  252. if (!event_cb) // Callback is not defined
  253. continue;
  254. sinfo.signo = signo;
  255. // Execute callback
  256. r = event_cb(eloop, FAUX_ELOOP_SIGNAL, &sinfo,
  257. sentry->context.user_data);
  258. // BOOL_FALSE return value means "break the loop"
  259. if (!r)
  260. stop = BOOL_TRUE;
  261. }
  262. continue; // Another fds are common, not signal
  263. }
  264. // File descriptor
  265. entry = (faux_eloop_fd_t *)faux_list_kfind(eloop->fds, &fd);
  266. assert(entry);
  267. if (!entry) // Something went wrong
  268. continue;
  269. event_cb = entry->context.event_cb;
  270. if (!event_cb)
  271. event_cb = eloop->default_event_cb;
  272. if (!event_cb) // Callback function is not defined for this event
  273. continue;
  274. info.fd = fd;
  275. info.revents = pollfd->revents;
  276. // Execute callback
  277. r = event_cb(eloop, FAUX_ELOOP_FD, &info, entry->context.user_data);
  278. // BOOL_FALSE return value means "break the loop"
  279. if (!r)
  280. stop = BOOL_TRUE;
  281. }
  282. } // Loop end
  283. #ifdef HAVE_SIGNALFD
  284. // Close signal file descriptor
  285. faux_pollfd_del_by_fd(eloop->pollfds, eloop->signal_fd);
  286. close(eloop->signal_fd);
  287. eloop->signal_fd = -1;
  288. #else // Standard signals. Restore signal handlers
  289. if (faux_list_len(eloop->signals) != 0) {
  290. faux_list_node_t *iter = faux_list_head(eloop->signals);
  291. faux_eloop_signal_t *sig = NULL;
  292. while ((sig = (faux_eloop_signal_t *)faux_list_each(&iter)))
  293. sigaction(sig->signo, &sig->oldact, NULL);
  294. }
  295. faux_pollfd_del_by_fd(eloop->pollfds, signal_pipe[0]);
  296. close(signal_pipe[0]);
  297. close(signal_pipe[1]);
  298. #endif
  299. // Unblock signals
  300. sigprocmask(SIG_SETMASK, &orig_sig_set, NULL);
  301. // Deactivate loop flag
  302. eloop->working = BOOL_FALSE;
  303. return retval;
  304. }
  305. bool_t faux_eloop_add_fd(faux_eloop_t *eloop, int fd, short events,
  306. faux_eloop_cb_f event_cb, void *user_data)
  307. {
  308. faux_eloop_fd_t *entry = NULL;
  309. faux_list_node_t *new_node = NULL;
  310. if (!eloop || (fd < 0))
  311. return BOOL_FALSE;
  312. entry = faux_zmalloc(sizeof(*entry));
  313. if (!entry)
  314. return BOOL_FALSE;
  315. entry->fd = fd;
  316. entry->events = events;
  317. entry->context.event_cb = event_cb;
  318. entry->context.user_data = user_data;
  319. if (!(new_node = faux_list_add(eloop->fds, entry))) {
  320. faux_free(entry);
  321. return BOOL_FALSE;
  322. }
  323. if (!faux_pollfd_add(eloop->pollfds, entry->fd, entry->events)) {
  324. faux_list_del(eloop->fds, new_node);
  325. faux_free(entry);
  326. return BOOL_FALSE;
  327. }
  328. return BOOL_TRUE;
  329. }
  330. bool_t faux_eloop_del_fd(faux_eloop_t *eloop, int fd)
  331. {
  332. if (!eloop || (fd < 0))
  333. return BOOL_FALSE;
  334. if (!faux_list_kdel(eloop->fds, &fd))
  335. return BOOL_FALSE;
  336. if (!faux_pollfd_del_by_fd(eloop->pollfds, fd))
  337. return BOOL_FALSE;
  338. return BOOL_TRUE;
  339. }
  340. bool_t faux_eloop_add_signal(faux_eloop_t *eloop, int signo,
  341. faux_eloop_cb_f event_cb, void *user_data)
  342. {
  343. faux_eloop_signal_t *entry = NULL;
  344. if (!eloop || (signo < 0))
  345. return BOOL_FALSE;
  346. if (sigismember(&eloop->sig_set, signo) == 1)
  347. return BOOL_FALSE; // Already exists
  348. // Firstly try to add signal to sigset. Library function will validate
  349. // signal number value.
  350. if (sigaddset(&eloop->sig_set, signo) < 0)
  351. return BOOL_FALSE; // Invalid signal number
  352. sigdelset(&eloop->sig_mask, signo);
  353. entry = faux_zmalloc(sizeof(*entry));
  354. if (!entry) {
  355. sigdelset(&eloop->sig_set, signo);
  356. sigaddset(&eloop->sig_mask, signo);
  357. return BOOL_FALSE;
  358. }
  359. entry->signo = signo;
  360. entry->context.event_cb = event_cb;
  361. entry->context.user_data = user_data;
  362. if (!faux_list_add(eloop->signals, entry)) {
  363. faux_free(entry);
  364. sigdelset(&eloop->sig_set, signo);
  365. sigaddset(&eloop->sig_mask, signo);
  366. return BOOL_FALSE;
  367. }
  368. if (eloop->working) { // Add signal on the fly
  369. #ifdef HAVE_SIGNALFD
  370. // Reattach signalfd handler with updated sig_set
  371. eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
  372. SIGNALFD_FLAGS);
  373. #else // Standard signals
  374. struct sigaction sig_act = {};
  375. sig_act.sa_flags = 0;
  376. sig_act.sa_mask = eloop->sig_set;
  377. sig_act.sa_handler = &faux_eloop_static_sighandler;
  378. sigaction(signo, &sig_act, &entry->oldact);
  379. #endif
  380. }
  381. return BOOL_TRUE;
  382. }
  383. bool_t faux_eloop_del_signal(faux_eloop_t *eloop, int signo)
  384. {
  385. if (!eloop || (signo < 0))
  386. return BOOL_FALSE;
  387. if (sigismember(&eloop->sig_set, signo) != 1)
  388. return BOOL_FALSE; // Doesn't exist
  389. sigdelset(&eloop->sig_set, signo);
  390. sigaddset(&eloop->sig_mask, signo);
  391. if (eloop->working) { // Del signal on the fly
  392. #ifdef HAVE_SIGNALFD
  393. // Reattach signalfd handler with updated sig_set
  394. eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
  395. SIGNALFD_FLAGS);
  396. #else // Standard signals
  397. faux_eloop_signal_t *sig = faux_list_kfind(eloop->signals, &signo);
  398. sigaction(signo, &sig->oldact, NULL);
  399. #endif
  400. }
  401. faux_list_kdel(eloop->signals, &signo);
  402. return BOOL_TRUE;
  403. }
  404. static faux_eloop_context_t *faux_eloop_new_context(
  405. faux_eloop_cb_f event_cb, void *data)
  406. {
  407. faux_eloop_context_t *context = NULL;
  408. context = faux_zmalloc(sizeof(*context));
  409. assert(context);
  410. if (!context)
  411. return NULL;
  412. context->event_cb = event_cb;
  413. context->user_data = data;
  414. return context;
  415. }
  416. faux_ev_t *faux_eloop_add_sched_once(faux_eloop_t *eloop, const struct timespec *time,
  417. int ev_id, faux_eloop_cb_f event_cb, void *data)
  418. {
  419. faux_eloop_context_t *context = NULL;
  420. faux_ev_t *ev = NULL;
  421. assert(eloop);
  422. if (!eloop)
  423. return NULL;
  424. context = faux_eloop_new_context(event_cb, data);
  425. assert(context);
  426. if (!context)
  427. return NULL;
  428. if (!(ev = faux_sched_once(eloop->sched, time, ev_id, context))) {
  429. faux_free(context);
  430. return NULL;
  431. }
  432. faux_ev_set_free_data_cb(ev, faux_free);
  433. return ev;
  434. }
  435. faux_ev_t *faux_eloop_add_sched_once_delayed(faux_eloop_t *eloop, const struct timespec *interval,
  436. int ev_id, faux_eloop_cb_f event_cb, void *data)
  437. {
  438. faux_eloop_context_t *context = NULL;
  439. faux_ev_t *ev = NULL;
  440. assert(eloop);
  441. if (!eloop)
  442. return NULL;
  443. context = faux_eloop_new_context(event_cb, data);
  444. assert(context);
  445. if (!context)
  446. return NULL;
  447. if (!(ev = faux_sched_once_delayed(eloop->sched, interval, ev_id, context))) {
  448. faux_free(context);
  449. return NULL;
  450. }
  451. faux_ev_set_free_data_cb(ev, faux_free);
  452. return ev;
  453. }
  454. faux_ev_t *faux_eloop_add_sched_periodic(faux_eloop_t *eloop, const struct timespec *time,
  455. int ev_id, faux_eloop_cb_f event_cb, void *data,
  456. const struct timespec *period, unsigned int cycle_num)
  457. {
  458. faux_eloop_context_t *context = NULL;
  459. faux_ev_t *ev = NULL;
  460. assert(eloop);
  461. if (!eloop)
  462. return NULL;
  463. context = faux_eloop_new_context(event_cb, data);
  464. assert(context);
  465. if (!context)
  466. return NULL;
  467. if (!(ev = faux_sched_periodic(eloop->sched, time, ev_id, context,
  468. period, cycle_num))) {
  469. faux_free(context);
  470. return NULL;
  471. }
  472. faux_ev_set_free_data_cb(ev, faux_free);
  473. return ev;
  474. }
  475. faux_ev_t *faux_eloop_add_sched_periodic_delayed(faux_eloop_t *eloop,
  476. int ev_id, faux_eloop_cb_f event_cb, void *data,
  477. const struct timespec *period, unsigned int cycle_num)
  478. {
  479. faux_eloop_context_t *context = NULL;
  480. faux_ev_t *ev = NULL;
  481. assert(eloop);
  482. if (!eloop)
  483. return NULL;
  484. context = faux_eloop_new_context(event_cb, data);
  485. assert(context);
  486. if (!context)
  487. return NULL;
  488. if (!(ev = faux_sched_periodic_delayed(eloop->sched, ev_id, context,
  489. period, cycle_num))) {
  490. faux_free(context);
  491. return NULL;
  492. }
  493. faux_ev_set_free_data_cb(ev, faux_free);
  494. return ev;
  495. }
  496. bool_t faux_eloop_del_sched(faux_eloop_t *eloop, int id)
  497. {
  498. assert(eloop);
  499. if (!eloop)
  500. return BOOL_FALSE;
  501. faux_sched_del_by_id(eloop->sched, id);
  502. return BOOL_TRUE;
  503. }