eloop.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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. #endif
  30. static int faux_eloop_sched_compare(const void *first, const void *second)
  31. {
  32. const faux_eloop_sched_t *f = (const faux_eloop_sched_t *)first;
  33. const faux_eloop_sched_t *s = (const faux_eloop_sched_t *)second;
  34. return (f->ev_id - s->ev_id);
  35. }
  36. static int faux_eloop_sched_kcompare(const void *key, const void *list_item)
  37. {
  38. int *f = (int *)key;
  39. const faux_eloop_sched_t *s = (const faux_eloop_sched_t *)list_item;
  40. return (*f - s->ev_id);
  41. }
  42. static int faux_eloop_fd_compare(const void *first, const void *second)
  43. {
  44. const faux_eloop_fd_t *f = (const faux_eloop_fd_t *)first;
  45. const faux_eloop_fd_t *s = (const faux_eloop_fd_t *)second;
  46. return (f->fd - s->fd);
  47. }
  48. static int faux_eloop_fd_kcompare(const void *key, const void *list_item)
  49. {
  50. int *f = (int *)key;
  51. const faux_eloop_fd_t *s = (const faux_eloop_fd_t *)list_item;
  52. return (*f - s->fd);
  53. }
  54. static int faux_eloop_signal_compare(const void *first, const void *second)
  55. {
  56. const faux_eloop_signal_t *f = (const faux_eloop_signal_t *)first;
  57. const faux_eloop_signal_t *s = (const faux_eloop_signal_t *)second;
  58. return (f->signo - s->signo);
  59. }
  60. static int faux_eloop_signal_kcompare(const void *key, const void *list_item)
  61. {
  62. int *f = (int *)key;
  63. const faux_eloop_signal_t *s = (const faux_eloop_signal_t *)list_item;
  64. return (*f - s->signo);
  65. }
  66. faux_eloop_t *faux_eloop_new(faux_eloop_cb_f *default_event_cb)
  67. {
  68. faux_eloop_t *eloop = NULL;
  69. eloop = faux_zmalloc(sizeof(*eloop));
  70. assert(eloop);
  71. if (!eloop)
  72. return NULL;
  73. // Init
  74. eloop->working = BOOL_FALSE;
  75. eloop->default_event_cb = default_event_cb;
  76. // Sched
  77. eloop->scheds = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  78. faux_eloop_sched_compare, faux_eloop_sched_kcompare, faux_free);
  79. assert(eloop->scheds);
  80. eloop->faux_sched = faux_sched_new();
  81. assert(eloop->faux_sched);
  82. // FD
  83. eloop->fds = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  84. faux_eloop_fd_compare, faux_eloop_fd_kcompare, faux_free);
  85. assert(eloop->fds);
  86. eloop->pollfds = faux_pollfd_new();
  87. assert(eloop->pollfds);
  88. // Signal
  89. eloop->signals = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  90. faux_eloop_signal_compare, faux_eloop_signal_kcompare, faux_free);
  91. assert(eloop->signals);
  92. sigemptyset(&eloop->sig_set);
  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->faux_sched);
  106. faux_list_free(eloop->scheds);
  107. faux_free(eloop);
  108. }
  109. bool_t faux_eloop_loop(faux_eloop_t *eloop)
  110. {
  111. bool_t retval = BOOL_TRUE;
  112. bool_t stop = BOOL_FALSE;
  113. sigset_t blocked_signals;
  114. sigset_t orig_sig_set;
  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. #endif
  131. /*
  132. // Set signal handler
  133. syslog(LOG_DEBUG, "Set signal handlers\n");
  134. sigemptyset(&sig_set);
  135. sigaddset(&sig_set, SIGTERM);
  136. sigaddset(&sig_set, SIGINT);
  137. sigaddset(&sig_set, SIGQUIT);
  138. sig_act.sa_flags = 0;
  139. sig_act.sa_mask = sig_set;
  140. sig_act.sa_handler = &sighandler;
  141. sigaction(SIGTERM, &sig_act, NULL);
  142. sigaction(SIGINT, &sig_act, NULL);
  143. sigaction(SIGQUIT, &sig_act, NULL);
  144. // SIGHUP handler
  145. sigemptyset(&sig_set);
  146. sigaddset(&sig_set, SIGHUP);
  147. sig_act.sa_flags = 0;
  148. sig_act.sa_mask = sig_set;
  149. sig_act.sa_handler = &sighup_handler;
  150. sigaction(SIGHUP, &sig_act, NULL);
  151. // SIGCHLD handler
  152. sigemptyset(&sig_set);
  153. sigaddset(&sig_set, SIGCHLD);
  154. sig_act.sa_flags = 0;
  155. sig_act.sa_mask = sig_set;
  156. sig_act.sa_handler = &sigchld_handler;
  157. sigaction(SIGCHLD, &sig_act, NULL);
  158. */
  159. // Main loop
  160. while (!stop) {
  161. int sn = 0;
  162. struct timespec *timeout = NULL;
  163. // struct timespec next_interval = {};
  164. faux_pollfd_iterator_t pollfd_iter;
  165. struct pollfd *pollfd = NULL;
  166. // pid_t pid = -1;
  167. // Re-read config file on SIGHUP
  168. /* if (sighup) {
  169. if (access(opts->cfgfile, R_OK) == 0) {
  170. syslog(LOG_INFO, "Re-reading config file \"%s\"\n", opts->cfgfile);
  171. if (config_parse(opts->cfgfile, opts) < 0)
  172. syslog(LOG_ERR, "Error while config file parsing.\n");
  173. } else if (opts->cfgfile_userdefined) {
  174. syslog(LOG_ERR, "Can't find config file \"%s\"\n", opts->cfgfile);
  175. }
  176. sighup = 0;
  177. }
  178. */
  179. // Find out next scheduled interval
  180. /* if (faux_sched_next_interval(eloop->sched, &next_interval) < 0)
  181. timeout = NULL;
  182. else
  183. timeout = &next_interval;
  184. */
  185. // Wait for events
  186. // sn = ppoll(faux_pollfd_vector(fds), faux_pollfd_len(fds), timeout, &orig_sig_set);
  187. sn = ppoll(faux_pollfd_vector(eloop->pollfds), faux_pollfd_len(eloop->pollfds), timeout, NULL);
  188. if (sn < 0) {
  189. if ((EAGAIN == errno) || (EINTR == errno))
  190. continue;
  191. retval = BOOL_FALSE;
  192. printf("ppoll() error\n");
  193. break;
  194. }
  195. // Scheduled event
  196. if (0 == sn) {
  197. // int id = 0; // Event idenftifier
  198. // void *data = NULL; // Event data
  199. // faux_eloop_info_sched_t info = {};
  200. printf("Sheduled event\n");
  201. // Some scheduled events
  202. /* while(faux_sched_pop(sched, &id, &data) == 0) {
  203. syslog(LOG_DEBUG, "sched: Update event\n");
  204. }
  205. */ continue;
  206. }
  207. // File descriptor
  208. faux_pollfd_init_iterator(eloop->pollfds, &pollfd_iter);
  209. while ((pollfd = faux_pollfd_each_active(eloop->pollfds, &pollfd_iter))) {
  210. int fd = pollfd->fd;
  211. faux_eloop_info_fd_t info = {};
  212. faux_eloop_cb_f *event_cb = NULL;
  213. faux_eloop_fd_t *entry = NULL;
  214. bool_t r = BOOL_TRUE;
  215. #ifdef HAVE_SIGNALFD
  216. // Read special signal file descriptor
  217. if (fd == eloop->signal_fd) {
  218. struct signalfd_siginfo signal_info = {};
  219. while (faux_read_block(fd, &signal_info,
  220. sizeof(signal_info)) == sizeof(signal_info)) {
  221. faux_eloop_info_signal_t sinfo = {};
  222. faux_eloop_signal_t *sentry =
  223. (faux_eloop_signal_t *)faux_list_kfind(
  224. eloop->signals, &signal_info.ssi_signo);
  225. if (!sentry) // Not registered signal. Drop it.
  226. continue;
  227. event_cb = sentry->context.event_cb;
  228. if (!event_cb)
  229. event_cb = eloop->default_event_cb;
  230. if (!event_cb) // Callback is not defined
  231. continue;
  232. sinfo.signo = sentry->signo;
  233. // Execute callback
  234. r = event_cb(eloop, FAUX_ELOOP_SIGNAL, &sinfo,
  235. sentry->context.user_data);
  236. // BOOL_FALSE return value means "break the loop"
  237. if (!r)
  238. stop = BOOL_TRUE;
  239. }
  240. continue; // Another fds are common, not signal
  241. }
  242. #endif
  243. // Prepare event data
  244. entry = (faux_eloop_fd_t *)faux_list_kfind(eloop->fds, &fd);
  245. assert(entry);
  246. if (!entry) // Something went wrong
  247. continue;
  248. event_cb = entry->context.event_cb;
  249. if (!event_cb)
  250. event_cb = eloop->default_event_cb;
  251. if (!event_cb) // Callback function is not defined for this event
  252. continue;
  253. info.fd = fd;
  254. info.revents = pollfd->revents;
  255. // Execute callback
  256. r = event_cb(eloop, FAUX_ELOOP_FD, &info, entry->context.user_data);
  257. // BOOL_FALSE return value means "break the loop"
  258. if (!r)
  259. stop = BOOL_TRUE;
  260. }
  261. } // Loop end
  262. #ifdef HAVE_SIGNALFD
  263. // Close signal file descriptor
  264. faux_pollfd_del_by_fd(eloop->pollfds, eloop->signal_fd);
  265. close(eloop->signal_fd);
  266. eloop->signal_fd = -1;
  267. #endif
  268. // Unblock signals
  269. sigprocmask(SIG_SETMASK, &orig_sig_set, NULL);
  270. // Deactivate loop flag
  271. eloop->working = BOOL_FALSE;
  272. return retval;
  273. }
  274. bool_t faux_eloop_add_fd(faux_eloop_t *eloop, int fd, short events,
  275. faux_eloop_cb_f *event_cb, void *user_data)
  276. {
  277. faux_eloop_fd_t *entry = NULL;
  278. faux_list_node_t *new_node = NULL;
  279. if (!eloop || (fd < 0))
  280. return BOOL_FALSE;
  281. entry = faux_zmalloc(sizeof(*entry));
  282. if (!entry)
  283. return BOOL_FALSE;
  284. entry->fd = fd;
  285. entry->events = events;
  286. entry->context.event_cb = event_cb;
  287. entry->context.user_data = user_data;
  288. if (!(new_node = faux_list_add(eloop->fds, entry))) {
  289. faux_free(entry);
  290. return BOOL_FALSE;
  291. }
  292. if (!faux_pollfd_add(eloop->pollfds, entry->fd, entry->events)) {
  293. faux_list_del(eloop->fds, new_node);
  294. faux_free(entry);
  295. return BOOL_FALSE;
  296. }
  297. return BOOL_TRUE;
  298. }
  299. bool_t faux_eloop_del_fd(faux_eloop_t *eloop, int fd)
  300. {
  301. if (!eloop || (fd < 0))
  302. return BOOL_FALSE;
  303. if (faux_list_kdel(eloop->fds, &fd) < 0)
  304. return BOOL_FALSE;
  305. if (faux_pollfd_del_by_fd(eloop->pollfds, fd) < 0)
  306. return BOOL_FALSE;
  307. return BOOL_TRUE;
  308. }
  309. bool_t faux_eloop_add_signal(faux_eloop_t *eloop, int signo,
  310. faux_eloop_cb_f *event_cb, void *user_data)
  311. {
  312. faux_eloop_signal_t *entry = NULL;
  313. if (!eloop || (signo < 0))
  314. return BOOL_FALSE;
  315. if (sigismember(&eloop->sig_set, signo) == 1)
  316. return BOOL_FALSE; // Already exists
  317. // Firstly try to add signal to sigset. Library function will validate
  318. // signal number value.
  319. if (sigaddset(&eloop->sig_set, signo) < 0)
  320. return BOOL_FALSE; // Invalid signal number
  321. entry = faux_zmalloc(sizeof(*entry));
  322. if (!entry) {
  323. sigdelset(&eloop->sig_set, signo);
  324. return BOOL_FALSE;
  325. }
  326. entry->signo = signo;
  327. entry->context.event_cb = event_cb;
  328. entry->context.user_data = user_data;
  329. if (!faux_list_add(eloop->signals, entry)) {
  330. faux_free(entry);
  331. sigdelset(&eloop->sig_set, signo);
  332. return BOOL_FALSE;
  333. }
  334. if (eloop->working) { // Add signal on the fly
  335. #ifdef HAVE_SIGNALFD
  336. // Reattach signalfd handler with updated sig_set
  337. eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
  338. SIGNALFD_FLAGS);
  339. #endif
  340. }
  341. return BOOL_TRUE;
  342. }
  343. bool_t faux_eloop_del_signal(faux_eloop_t *eloop, int signo)
  344. {
  345. if (!eloop || (signo < 0))
  346. return BOOL_FALSE;
  347. if (sigismember(&eloop->sig_set, signo) != 1)
  348. return BOOL_FALSE; // Doesn't exist
  349. sigdelset(&eloop->sig_set, signo);
  350. faux_list_kdel(eloop->signals, &signo);
  351. if (eloop->working) { // Add signal on the fly
  352. #ifdef HAVE_SIGNALFD
  353. // Reattach signalfd handler with updated sig_set
  354. eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
  355. SIGNALFD_FLAGS);
  356. #endif
  357. }
  358. return BOOL_TRUE;
  359. }