eloop.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  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 all signals.
  129. // Unneeded signals will be filtered out later.
  130. eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
  131. SIGNALFD_FLAGS);
  132. faux_pollfd_add(eloop->pollfds, eloop->signal_fd, POLLIN);
  133. #else // Standard signal processing
  134. #ifdef PPOLL
  135. sigset_for_ppoll = &eloop->sig_mask;
  136. #endif // HAVE_PPOLL
  137. // Create signal pipe pair to get signal number on pipe read end
  138. pipe(signal_pipe);
  139. fcntl(signal_pipe[0], F_SETFD, FD_CLOEXEC);
  140. fflags = fcntl(signal_pipe[0], F_GETFL);
  141. fcntl(signal_pipe[0], F_SETFL, fflags | O_NONBLOCK);
  142. fcntl(signal_pipe[1], F_SETFD, FD_CLOEXEC);
  143. fflags = fcntl(signal_pipe[1], F_GETFL);
  144. fcntl(signal_pipe[1], F_SETFL, fflags | O_NONBLOCK);
  145. faux_eloop_static_user_data = &signal_pipe[1];
  146. faux_pollfd_add(eloop->pollfds, signal_pipe[0], POLLIN);
  147. if (faux_list_len(eloop->signals) != 0) {
  148. faux_list_node_t *iter = faux_list_head(eloop->signals);
  149. faux_eloop_signal_t *sig = NULL;
  150. struct sigaction sig_act = {};
  151. sig_act.sa_flags = 0;
  152. sig_act.sa_mask = eloop->sig_set;
  153. sig_act.sa_handler = &faux_eloop_static_sighandler;
  154. while ((sig = (faux_eloop_signal_t *)faux_list_each(&iter)))
  155. sigaction(sig->signo, &sig_act, &sig->oldact);
  156. }
  157. #endif // HAVE_SIGNALFD
  158. // Main loop
  159. while (!stop) {
  160. int sn = 0;
  161. struct timespec *timeout = NULL;
  162. struct timespec next_interval = {};
  163. faux_pollfd_iterator_t pollfd_iter;
  164. struct pollfd *pollfd = NULL;
  165. // Find out next scheduled interval
  166. if (!faux_sched_next_interval(eloop->sched, &next_interval))
  167. timeout = NULL;
  168. else
  169. timeout = &next_interval;
  170. // Wait for events
  171. #ifdef HAVE_PPOLL
  172. sn = ppoll(faux_pollfd_vector(eloop->pollfds),
  173. faux_pollfd_len(eloop->pollfds), timeout, sigset_for_ppoll);
  174. #else // poll()
  175. sigprocmask(SIG_SETMASK, &eloop->sig_mask, NULL);
  176. sn = poll(faux_pollfd_vector(eloop->pollfds),
  177. faux_pollfd_len(eloop->pollfds),
  178. timeout ? TIMESPEC_TO_MILISECONDS(next_interval) : -1);
  179. sigprocmask(SIG_SETMASK, &blocked_signals, NULL);
  180. #endif // HAVE_PPOLL
  181. // Error or signal
  182. if (sn < 0) {
  183. // Let poll() read signal pipe or signalfd on next step
  184. if (EINTR == errno)
  185. continue;
  186. retval = BOOL_FALSE;
  187. break;
  188. }
  189. // Scheduled event
  190. if (0 == sn) {
  191. faux_ev_t *ev = NULL;
  192. // Some scheduled events
  193. while((ev = faux_sched_pop(eloop->sched))) {
  194. faux_eloop_info_sched_t info = {};
  195. bool_t r = BOOL_TRUE;
  196. int ev_id = faux_ev_id(ev);
  197. faux_eloop_context_t *context =
  198. (faux_eloop_context_t *)faux_ev_data(ev);
  199. faux_eloop_cb_f event_cb = context->event_cb;
  200. void *user_data = context->user_data;
  201. if (!faux_ev_is_busy(ev))
  202. faux_ev_free(ev);
  203. if (!event_cb)
  204. event_cb = eloop->default_event_cb;
  205. if (!event_cb) // Callback is not defined
  206. continue;
  207. info.ev_id = ev_id;
  208. // Execute callback
  209. r = event_cb(eloop, FAUX_ELOOP_SCHED, &info,
  210. user_data);
  211. // BOOL_FALSE return value means "break the loop"
  212. if (!r)
  213. stop = BOOL_TRUE;
  214. }
  215. continue;
  216. }
  217. // File descriptor
  218. faux_pollfd_init_iterator(eloop->pollfds, &pollfd_iter);
  219. while ((pollfd = faux_pollfd_each_active(eloop->pollfds, &pollfd_iter))) {
  220. int fd = pollfd->fd;
  221. faux_eloop_info_fd_t info = {};
  222. faux_eloop_cb_f event_cb = NULL;
  223. faux_eloop_fd_t *entry = NULL;
  224. bool_t r = BOOL_TRUE;
  225. // Read special signal file descriptor
  226. #ifdef HAVE_SIGNALFD
  227. if (fd == eloop->signal_fd) {
  228. struct signalfd_siginfo signal_info = {};
  229. while (faux_read_block(fd, &signal_info,
  230. sizeof(signal_info)) == sizeof(signal_info)) {
  231. int signo = signal_info.ssi_signo;
  232. #else
  233. if (fd == signal_pipe[0]) {
  234. int tmp = 0;
  235. while (faux_read_block(fd, &tmp,
  236. sizeof(tmp)) == sizeof(tmp)) {
  237. int signo = tmp;
  238. #endif // HAVE_SIGNALFD
  239. faux_eloop_info_signal_t sinfo = {};
  240. faux_eloop_signal_t *sentry =
  241. (faux_eloop_signal_t *)faux_list_kfind(
  242. eloop->signals, &signo);
  243. if (!sentry) // Not registered signal. Drop it.
  244. continue;
  245. event_cb = sentry->context.event_cb;
  246. if (!event_cb)
  247. event_cb = eloop->default_event_cb;
  248. if (!event_cb) // Callback is not defined
  249. continue;
  250. sinfo.signo = signo;
  251. // Execute callback
  252. r = event_cb(eloop, FAUX_ELOOP_SIGNAL, &sinfo,
  253. sentry->context.user_data);
  254. // BOOL_FALSE return value means "break the loop"
  255. if (!r)
  256. stop = BOOL_TRUE;
  257. }
  258. continue; // Another fds are common, not signal
  259. }
  260. // Prepare event data
  261. entry = (faux_eloop_fd_t *)faux_list_kfind(eloop->fds, &fd);
  262. assert(entry);
  263. if (!entry) // Something went wrong
  264. continue;
  265. event_cb = entry->context.event_cb;
  266. if (!event_cb)
  267. event_cb = eloop->default_event_cb;
  268. if (!event_cb) // Callback function is not defined for this event
  269. continue;
  270. info.fd = fd;
  271. info.revents = pollfd->revents;
  272. // Execute callback
  273. r = event_cb(eloop, FAUX_ELOOP_FD, &info, entry->context.user_data);
  274. // BOOL_FALSE return value means "break the loop"
  275. if (!r)
  276. stop = BOOL_TRUE;
  277. }
  278. } // Loop end
  279. #ifdef HAVE_SIGNALFD
  280. // Close signal file descriptor
  281. faux_pollfd_del_by_fd(eloop->pollfds, eloop->signal_fd);
  282. close(eloop->signal_fd);
  283. eloop->signal_fd = -1;
  284. #else // Standard signals. Restore signal handlers
  285. if (faux_list_len(eloop->signals) != 0) {
  286. faux_list_node_t *iter = faux_list_head(eloop->signals);
  287. faux_eloop_signal_t *sig = NULL;
  288. while ((sig = (faux_eloop_signal_t *)faux_list_each(&iter)))
  289. sigaction(sig->signo, &sig->oldact, NULL);
  290. }
  291. faux_pollfd_del_by_fd(eloop->pollfds, signal_pipe[0]);
  292. close(signal_pipe[0]);
  293. close(signal_pipe[1]);
  294. #endif
  295. // Unblock signals
  296. sigprocmask(SIG_SETMASK, &orig_sig_set, NULL);
  297. // Deactivate loop flag
  298. eloop->working = BOOL_FALSE;
  299. return retval;
  300. }
  301. bool_t faux_eloop_add_fd(faux_eloop_t *eloop, int fd, short events,
  302. faux_eloop_cb_f event_cb, void *user_data)
  303. {
  304. faux_eloop_fd_t *entry = NULL;
  305. faux_list_node_t *new_node = NULL;
  306. if (!eloop || (fd < 0))
  307. return BOOL_FALSE;
  308. entry = faux_zmalloc(sizeof(*entry));
  309. if (!entry)
  310. return BOOL_FALSE;
  311. entry->fd = fd;
  312. entry->events = events;
  313. entry->context.event_cb = event_cb;
  314. entry->context.user_data = user_data;
  315. if (!(new_node = faux_list_add(eloop->fds, entry))) {
  316. faux_free(entry);
  317. return BOOL_FALSE;
  318. }
  319. if (!faux_pollfd_add(eloop->pollfds, entry->fd, entry->events)) {
  320. faux_list_del(eloop->fds, new_node);
  321. faux_free(entry);
  322. return BOOL_FALSE;
  323. }
  324. return BOOL_TRUE;
  325. }
  326. bool_t faux_eloop_del_fd(faux_eloop_t *eloop, int fd)
  327. {
  328. if (!eloop || (fd < 0))
  329. return BOOL_FALSE;
  330. if (!faux_list_kdel(eloop->fds, &fd))
  331. return BOOL_FALSE;
  332. if (!faux_pollfd_del_by_fd(eloop->pollfds, fd))
  333. return BOOL_FALSE;
  334. return BOOL_TRUE;
  335. }
  336. bool_t faux_eloop_add_signal(faux_eloop_t *eloop, int signo,
  337. faux_eloop_cb_f event_cb, void *user_data)
  338. {
  339. faux_eloop_signal_t *entry = NULL;
  340. if (!eloop || (signo < 0))
  341. return BOOL_FALSE;
  342. if (sigismember(&eloop->sig_set, signo) == 1)
  343. return BOOL_FALSE; // Already exists
  344. // Firstly try to add signal to sigset. Library function will validate
  345. // signal number value.
  346. if (sigaddset(&eloop->sig_set, signo) < 0)
  347. return BOOL_FALSE; // Invalid signal number
  348. sigdelset(&eloop->sig_mask, signo);
  349. entry = faux_zmalloc(sizeof(*entry));
  350. if (!entry) {
  351. sigdelset(&eloop->sig_set, signo);
  352. sigaddset(&eloop->sig_mask, signo);
  353. return BOOL_FALSE;
  354. }
  355. entry->signo = signo;
  356. entry->context.event_cb = event_cb;
  357. entry->context.user_data = user_data;
  358. if (!faux_list_add(eloop->signals, entry)) {
  359. faux_free(entry);
  360. sigdelset(&eloop->sig_set, signo);
  361. sigaddset(&eloop->sig_mask, signo);
  362. return BOOL_FALSE;
  363. }
  364. if (eloop->working) { // Add signal on the fly
  365. #ifdef HAVE_SIGNALFD
  366. // Reattach signalfd handler with updated sig_set
  367. eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
  368. SIGNALFD_FLAGS);
  369. #else // Standard signals
  370. struct sigaction sig_act = {};
  371. sig_act.sa_flags = 0;
  372. sig_act.sa_mask = eloop->sig_set;
  373. sig_act.sa_handler = &faux_eloop_static_sighandler;
  374. sigaction(signo, &sig_act, &entry->oldact);
  375. #endif
  376. }
  377. return BOOL_TRUE;
  378. }
  379. bool_t faux_eloop_del_signal(faux_eloop_t *eloop, int signo)
  380. {
  381. if (!eloop || (signo < 0))
  382. return BOOL_FALSE;
  383. if (sigismember(&eloop->sig_set, signo) != 1)
  384. return BOOL_FALSE; // Doesn't exist
  385. sigdelset(&eloop->sig_set, signo);
  386. sigaddset(&eloop->sig_mask, signo);
  387. if (eloop->working) { // Del signal on the fly
  388. #ifdef HAVE_SIGNALFD
  389. // Reattach signalfd handler with updated sig_set
  390. eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
  391. SIGNALFD_FLAGS);
  392. #else // Standard signals
  393. faux_eloop_signal_t *sig = faux_list_kfind(eloop->signals, &signo);
  394. sigaction(signo, &sig->oldact, NULL);
  395. #endif
  396. }
  397. faux_list_kdel(eloop->signals, &signo);
  398. return BOOL_TRUE;
  399. }
  400. static faux_eloop_context_t *faux_eloop_new_context(
  401. faux_eloop_cb_f event_cb, void *data)
  402. {
  403. faux_eloop_context_t *context = NULL;
  404. context = faux_zmalloc(sizeof(*context));
  405. assert(context);
  406. if (!context)
  407. return NULL;
  408. context->event_cb = event_cb;
  409. context->user_data = data;
  410. return context;
  411. }
  412. bool_t faux_eloop_add_sched_once(faux_eloop_t *eloop, const struct timespec *time,
  413. int ev_id, faux_eloop_cb_f event_cb, void *data)
  414. {
  415. faux_eloop_context_t *context = NULL;
  416. faux_ev_t *ev = NULL;
  417. assert(eloop);
  418. if (!eloop)
  419. return BOOL_FALSE;
  420. if (faux_sched_id_exist(eloop->sched, ev_id))
  421. return BOOL_FALSE; // ID must be unique
  422. context = faux_eloop_new_context(event_cb, data);
  423. assert(context);
  424. if (!context)
  425. return BOOL_FALSE;
  426. if (!(ev = faux_sched_once(eloop->sched, time, ev_id, context))) {
  427. faux_free(context);
  428. return BOOL_FALSE;
  429. }
  430. faux_ev_set_free_data_cb(ev, faux_free);
  431. return BOOL_TRUE;
  432. }
  433. bool_t faux_eloop_add_sched_once_delayed(faux_eloop_t *eloop, const struct timespec *interval,
  434. int ev_id, faux_eloop_cb_f event_cb, void *data)
  435. {
  436. faux_eloop_context_t *context = NULL;
  437. faux_ev_t *ev = NULL;
  438. assert(eloop);
  439. if (!eloop)
  440. return BOOL_FALSE;
  441. if (faux_sched_id_exist(eloop->sched, ev_id))
  442. return BOOL_FALSE; // ID must be unique
  443. context = faux_eloop_new_context(event_cb, data);
  444. assert(context);
  445. if (!context)
  446. return BOOL_FALSE;
  447. if (!(ev = faux_sched_once_delayed(eloop->sched, interval, ev_id, context))) {
  448. faux_free(context);
  449. return BOOL_FALSE;
  450. }
  451. faux_ev_set_free_data_cb(ev, faux_free);
  452. return BOOL_TRUE;
  453. }
  454. bool_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 BOOL_FALSE;
  463. if (faux_sched_id_exist(eloop->sched, ev_id))
  464. return BOOL_FALSE; // ID must be unique
  465. context = faux_eloop_new_context(event_cb, data);
  466. assert(context);
  467. if (!context)
  468. return BOOL_FALSE;
  469. if (!(ev = faux_sched_periodic(eloop->sched, time, ev_id, context,
  470. period, cycle_num))) {
  471. faux_free(context);
  472. return BOOL_FALSE;
  473. }
  474. faux_ev_set_free_data_cb(ev, faux_free);
  475. return BOOL_TRUE;
  476. }
  477. bool_t faux_eloop_add_sched_periodic_delayed(faux_eloop_t *eloop,
  478. int ev_id, faux_eloop_cb_f event_cb, void *data,
  479. const struct timespec *period, unsigned int cycle_num)
  480. {
  481. faux_eloop_context_t *context = NULL;
  482. faux_ev_t *ev = NULL;
  483. assert(eloop);
  484. if (!eloop)
  485. return BOOL_FALSE;
  486. if (faux_sched_id_exist(eloop->sched, ev_id))
  487. return BOOL_FALSE; // ID must be unique
  488. context = faux_eloop_new_context(event_cb, data);
  489. assert(context);
  490. if (!context)
  491. return BOOL_FALSE;
  492. if (!(ev = faux_sched_periodic_delayed(eloop->sched, ev_id, context,
  493. period, cycle_num))) {
  494. faux_free(context);
  495. return BOOL_FALSE;
  496. }
  497. faux_ev_set_free_data_cb(ev, faux_free);
  498. return BOOL_TRUE;
  499. }
  500. bool_t faux_eloop_del_sched(faux_eloop_t *eloop, int id)
  501. {
  502. assert(eloop);
  503. if (!eloop)
  504. return BOOL_FALSE;
  505. faux_sched_del_by_id(eloop->sched, id);
  506. return BOOL_TRUE;
  507. }