/** * \brief Forks a timer process based on the local timer * * Forks a separate timer process running a local_timer.h type of timer * A pointer to the local_timer handle (allocated in shared memory) is * returned in lt_h. It can be used to add/delete more timers at runtime * (via local_timer_add()/local_timer_del() a.s.o). * If timers are added from separate processes, some form of locking must be * used (all the calls to local_timer* must be enclosed by locks if it * cannot be guaranteed that they cannot execute in the same time) * The timer "engine" must be run manually from the child process. For * example a very simple local timer process that just runs a single * periodic timer can be started in the following way: * struct local_timer* lt_h; * * pid=fork_local_timer_process(...., <_h); * if (pid==0){ * timer_init(&my_timer, my_timer_f, 0, 0); * local_timer_add(<_h, &my_timer, S_TO_TICKS(10), get_ticks_raw()); * while(1) { sleep(1); local_timer_run(lt, get_ticks_raw()); } * } * * @param child_id @see fork_process() * @param desc @see fork_process() * @param make_sock @see fork_process() * @param lt_h local_timer handler * @return pid to the parent, 0 to the child, -1 if error. */ int fork_local_timer_process(int child_id, char* desc, int make_sock, struct local_timer** lt_h) { int pid; struct local_timer* lt; lt=shm_malloc(sizeof(*lt)); if (lt==0) goto error; if (init_local_timer(lt, get_ticks_raw())<0) goto error; pid=fork_process(child_id, desc, make_sock); if (pid<0) goto error; *lt_h=lt; return pid; error: if (lt) shm_free(lt); return -1; }
void tcp_receive_loop(int unix_sock) { /* init */ tcpmain_sock=unix_sock; /* init com. socket */ if (init_io_wait(&io_w, get_max_open_fds(), tcp_poll_method)<0) goto error; tcp_reader_prev_ticks=get_ticks_raw(); if (init_local_timer(&tcp_reader_ltimer, get_ticks_raw())!=0) goto error; /* add the unix socket */ if (io_watch_add(&io_w, tcpmain_sock, POLLIN, F_TCPMAIN, 0)<0){ LM_CRIT("failed to add socket to the fd list\n"); goto error; } /* initialize the config framework */ if (cfg_child_init()) goto error; /* main loop */ switch(io_w.poll_method){ case POLL_POLL: while(1){ io_wait_loop_poll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_reader_timer_run(); } break; #ifdef HAVE_SELECT case POLL_SELECT: while(1){ io_wait_loop_select(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_reader_timer_run(); } break; #endif #ifdef HAVE_SIGIO_RT case POLL_SIGIO_RT: while(1){ io_wait_loop_sigio_rt(&io_w, TCP_CHILD_SELECT_TIMEOUT); tcp_reader_timer_run(); } break; #endif #ifdef HAVE_EPOLL case POLL_EPOLL_LT: while(1){ io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_reader_timer_run(); } break; case POLL_EPOLL_ET: while(1){ io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 1); tcp_reader_timer_run(); } break; #endif #ifdef HAVE_KQUEUE case POLL_KQUEUE: while(1){ io_wait_loop_kqueue(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_reader_timer_run(); } break; #endif #ifdef HAVE_DEVPOLL case POLL_DEVPOLL: while(1){ io_wait_loop_devpoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_reader_timer_run(); } break; #endif default: LM_CRIT("no support for poll method %s (%d)\n", poll_method_name(io_w.poll_method), io_w.poll_method); goto error; } error: destroy_io_wait(&io_w); LM_CRIT("exiting..."); exit(-1); }