eloop.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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 "faux/faux.h"
  21. #include "faux/str.h"
  22. #include "faux/net.h"
  23. #include "faux/sched.h"
  24. #include "faux/eloop.h"
  25. #include "private.h"
  26. static int faux_eloop_sched_compare(const void *first, const void *second)
  27. {
  28. const faux_eloop_sched_t *f = (const faux_eloop_sched_t *)first;
  29. const faux_eloop_sched_t *s = (const faux_eloop_sched_t *)second;
  30. return (f->ev_id - s->ev_id);
  31. }
  32. static int faux_eloop_sched_kcompare(const void *key, const void *list_item)
  33. {
  34. int *f = (int *)key;
  35. const faux_eloop_sched_t *s = (const faux_eloop_sched_t *)list_item;
  36. return (*f - s->ev_id);
  37. }
  38. static int faux_eloop_fd_compare(const void *first, const void *second)
  39. {
  40. const faux_eloop_fd_t *f = (const faux_eloop_fd_t *)first;
  41. const faux_eloop_fd_t *s = (const faux_eloop_fd_t *)second;
  42. return (f->fd - s->fd);
  43. }
  44. static int faux_eloop_fd_kcompare(const void *key, const void *list_item)
  45. {
  46. int *f = (int *)key;
  47. const faux_eloop_fd_t *s = (const faux_eloop_fd_t *)list_item;
  48. return (*f - s->fd);
  49. }
  50. static int faux_eloop_signal_compare(const void *first, const void *second)
  51. {
  52. const faux_eloop_signal_t *f = (const faux_eloop_signal_t *)first;
  53. const faux_eloop_signal_t *s = (const faux_eloop_signal_t *)second;
  54. return (f->signo - s->signo);
  55. }
  56. static int faux_eloop_signal_kcompare(const void *key, const void *list_item)
  57. {
  58. int *f = (int *)key;
  59. const faux_eloop_signal_t *s = (const faux_eloop_signal_t *)list_item;
  60. return (*f - s->signo);
  61. }
  62. faux_eloop_t *faux_eloop_new(faux_eloop_cb_f *default_event_cb)
  63. {
  64. faux_eloop_t *eloop = NULL;
  65. eloop = faux_zmalloc(sizeof(*eloop));
  66. assert(eloop);
  67. if (!eloop)
  68. return NULL;
  69. // Init
  70. eloop->default_event_cb = default_event_cb;
  71. // Sched
  72. eloop->scheds = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  73. faux_eloop_sched_compare, faux_eloop_sched_kcompare, faux_free);
  74. assert(eloop->scheds);
  75. eloop->faux_sched = faux_sched_new();
  76. assert(eloop->faux_sched);
  77. // FD
  78. eloop->fds = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  79. faux_eloop_fd_compare, faux_eloop_fd_kcompare, faux_free);
  80. assert(eloop->fds);
  81. eloop->pollfds = faux_pollfd_new();
  82. assert(eloop->pollfds);
  83. // Signal
  84. eloop->signals = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  85. faux_eloop_signal_compare, faux_eloop_signal_kcompare, faux_free);
  86. assert(eloop->signals);
  87. sigemptyset(&eloop->sig_set);
  88. return eloop;
  89. }
  90. void faux_eloop_free(faux_eloop_t *eloop)
  91. {
  92. if (!eloop)
  93. return;
  94. faux_list_free(eloop->signals);
  95. faux_pollfd_free(eloop->pollfds);
  96. faux_list_free(eloop->fds);
  97. faux_sched_free(eloop->faux_sched);
  98. faux_list_free(eloop->scheds);
  99. faux_free(eloop);
  100. }
  101. bool_t faux_eloop_loop(faux_eloop_t *eloop)
  102. {
  103. bool_t retval = BOOL_TRUE;
  104. bool_t stop = BOOL_FALSE;
  105. /*
  106. // Set signal handler
  107. syslog(LOG_DEBUG, "Set signal handlers\n");
  108. sigemptyset(&sig_set);
  109. sigaddset(&sig_set, SIGTERM);
  110. sigaddset(&sig_set, SIGINT);
  111. sigaddset(&sig_set, SIGQUIT);
  112. sig_act.sa_flags = 0;
  113. sig_act.sa_mask = sig_set;
  114. sig_act.sa_handler = &sighandler;
  115. sigaction(SIGTERM, &sig_act, NULL);
  116. sigaction(SIGINT, &sig_act, NULL);
  117. sigaction(SIGQUIT, &sig_act, NULL);
  118. // SIGHUP handler
  119. sigemptyset(&sig_set);
  120. sigaddset(&sig_set, SIGHUP);
  121. sig_act.sa_flags = 0;
  122. sig_act.sa_mask = sig_set;
  123. sig_act.sa_handler = &sighup_handler;
  124. sigaction(SIGHUP, &sig_act, NULL);
  125. // SIGCHLD handler
  126. sigemptyset(&sig_set);
  127. sigaddset(&sig_set, SIGCHLD);
  128. sig_act.sa_flags = 0;
  129. sig_act.sa_mask = sig_set;
  130. sig_act.sa_handler = &sigchld_handler;
  131. sigaction(SIGCHLD, &sig_act, NULL);
  132. // Block signals to prevent race conditions while loop and ppoll()
  133. // Catch signals while ppoll() only
  134. sigemptyset(&sig_set);
  135. sigaddset(&sig_set, SIGTERM);
  136. sigaddset(&sig_set, SIGINT);
  137. sigaddset(&sig_set, SIGQUIT);
  138. sigaddset(&sig_set, SIGHUP);
  139. sigaddset(&sig_set, SIGCHLD);
  140. sigprocmask(SIG_BLOCK, &sig_set, &orig_sig_set);
  141. */
  142. // Main loop
  143. while (!stop) {
  144. int sn = 0;
  145. struct timespec *timeout = NULL;
  146. // struct timespec next_interval = {};
  147. faux_pollfd_iterator_t pollfd_iter;
  148. struct pollfd *pollfd = NULL;
  149. // pid_t pid = -1;
  150. // Re-read config file on SIGHUP
  151. /* if (sighup) {
  152. if (access(opts->cfgfile, R_OK) == 0) {
  153. syslog(LOG_INFO, "Re-reading config file \"%s\"\n", opts->cfgfile);
  154. if (config_parse(opts->cfgfile, opts) < 0)
  155. syslog(LOG_ERR, "Error while config file parsing.\n");
  156. } else if (opts->cfgfile_userdefined) {
  157. syslog(LOG_ERR, "Can't find config file \"%s\"\n", opts->cfgfile);
  158. }
  159. sighup = 0;
  160. }
  161. */
  162. // Find out next scheduled interval
  163. /* if (faux_sched_next_interval(eloop->sched, &next_interval) < 0)
  164. timeout = NULL;
  165. else
  166. timeout = &next_interval;
  167. */
  168. // Wait for events
  169. // sn = ppoll(faux_pollfd_vector(fds), faux_pollfd_len(fds), timeout, &orig_sig_set);
  170. sn = ppoll(faux_pollfd_vector(eloop->pollfds), faux_pollfd_len(eloop->pollfds), timeout, NULL);
  171. if (sn < 0) {
  172. if ((EAGAIN == errno) || (EINTR == errno))
  173. continue;
  174. retval = BOOL_FALSE;
  175. printf("ppoll() error\n");
  176. break;
  177. }
  178. // Scheduled event
  179. if (0 == sn) {
  180. // int id = 0; // Event idenftifier
  181. // void *data = NULL; // Event data
  182. // faux_eloop_info_sched_t info = {};
  183. printf("Sheduled event\n");
  184. // Some scheduled events
  185. /* while(faux_sched_pop(sched, &id, &data) == 0) {
  186. syslog(LOG_DEBUG, "sched: Update event\n");
  187. }
  188. */ continue;
  189. }
  190. // File descriptor
  191. faux_pollfd_init_iterator(eloop->pollfds, &pollfd_iter);
  192. while ((pollfd = faux_pollfd_each_active(eloop->pollfds, &pollfd_iter))) {
  193. int fd = pollfd->fd;
  194. faux_eloop_info_fd_t info = {};
  195. faux_eloop_cb_f *event_cb = NULL;
  196. faux_eloop_fd_t *entry = NULL;
  197. bool_t r = BOOL_TRUE;
  198. // Prepare event data
  199. entry = (faux_eloop_fd_t *)faux_list_kfind(eloop->fds, &fd);
  200. assert(entry);
  201. if (!entry) // Something went wrong
  202. continue;
  203. event_cb = entry->context.event_cb;
  204. if (!event_cb)
  205. event_cb = eloop->default_event_cb;
  206. if (!event_cb) // Callback function is not defined for this event
  207. continue;
  208. info.fd = fd;
  209. info.revents = pollfd->revents;
  210. // Execute callback
  211. r = event_cb(eloop, FAUX_ELOOP_FD, &info, entry->context.user_data);
  212. // BOOL_FALSE return value means "break the loop"
  213. if (!r)
  214. stop = BOOL_TRUE;
  215. }
  216. } // Loop end
  217. return retval;
  218. }
  219. bool_t faux_eloop_add_fd(faux_eloop_t *eloop, int fd, short events,
  220. faux_eloop_cb_f *event_cb, void *user_data)
  221. {
  222. faux_eloop_fd_t *entry = NULL;
  223. faux_list_node_t *new_node = NULL;
  224. if (!eloop || (fd < 0))
  225. return BOOL_FALSE;
  226. entry = faux_zmalloc(sizeof(*entry));
  227. if (!entry)
  228. return BOOL_FALSE;
  229. entry->fd = fd;
  230. entry->events = events;
  231. entry->context.event_cb = event_cb;
  232. entry->context.user_data = user_data;
  233. if (!(new_node = faux_list_add(eloop->fds, entry))) {
  234. faux_free(entry);
  235. return BOOL_FALSE;
  236. }
  237. if (!faux_pollfd_add(eloop->pollfds, entry->fd, entry->events)) {
  238. faux_list_del(eloop->fds, new_node);
  239. faux_free(entry);
  240. return BOOL_FALSE;
  241. }
  242. return BOOL_TRUE;
  243. }
  244. bool_t faux_eloop_del_fd(faux_eloop_t *eloop, int fd)
  245. {
  246. if (!eloop || (fd < 0))
  247. return BOOL_FALSE;
  248. if (faux_list_kdel(eloop->fds, &fd) < 0)
  249. return BOOL_FALSE;
  250. if (faux_pollfd_del_by_fd(eloop->pollfds, fd) < 0)
  251. return BOOL_FALSE;
  252. return BOOL_TRUE;
  253. }