eloop.c 15 KB

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