static int lua_events_wait(lua_State *L) { // All the parameters here are the wait_id userdata. We need to put them into an array. size_t event_count = lua_gettop(L); struct wait_id ids[event_count]; for (size_t i = 1; i <= event_count; i ++) // Check each one is the wait_id we provided memcpy(&ids[i - 1], luaL_checkudata(L, i, WAIT_ID_META), sizeof ids[i - 1]); struct events *events = extract_registry(L, "events"); events_wait(events, event_count, ids); // Nothing returned return 0; }
static int worker_server(worker *info) { /* server worker */ int nfds, fd, i; worker *w; int num = info->num; master_server *master_srv = info->master_srv; /* attach the shared mem */ int shmid; key_t key = master_srv->pid + num; if ((shmid = shmget(key, sizeof(worker), 0666)) < 0) { perror ("ERROR shmget"); exit (1); } /* attach it */ if ((w = shmat(shmid, NULL, 0)) == (char*) -1) { perror ("ERROR shmat"); exit (1); } /* process id */ w->pid = getpid(); /* worker process started */ printf (" * Worker process #%d is started.\n", num+1); /* pre-setup worker connections */ w->conns = connection_setup(master_srv); /* create a new event handler for this worker */ event_handler *ev_handler = events_create(master_srv->config->max_clients); /* share the event fd */ w->ev_handler.fd = ev_handler->fd; /* starting keep-alive clean-up thread */ printf (" * Starting keep-alive clean-up thread for worker #%d.\n", num+1); pthread_t thread_keep_alive; int rc_cleanup = pthread_create(&thread_keep_alive, NULL, worker_keep_alive_cleanup, w); /* starting heartbeat thread */ printf (" * Starting heartbeat thread for worker #%d.\n", num+1); pthread_t thread_heartbeat; int rc_heartbeat = pthread_create(&thread_heartbeat, NULL, worker_heartbeat, w); /* entering main loop... */ while (master_srv->running) { /* check for new data */ if ((nfds = events_wait(ev_handler, master_srv)) == -1) { perror ("ERROR epoll_pwait"); } for (i = 0; i < nfds; ++i) { /* data received */ fd = events_get_fd(ev_handler, i); connection *conn = w->conns[fd]; if (events_closed(ev_handler, i)) { /* the other end closed the connection */ conn->status = CONN_INACTIVE; printf (" * Other end closed the connection\n"); } else if (conn->status == CONN_INACTIVE) { /* this connection is inactive, initiate a new connection */ connection_start (master_srv, conn); } connection_handle (w, conn); /* closing */ if (conn->status == CONN_INACTIVE) { if (events_del_event(ev_handler, fd) == -1) { perror ("ERROR events_del_event"); } close (fd); } } } printf (" * Shutting down worker process #%d...\n", num+1); /* free event handler */ events_free (ev_handler, master_srv->config->max_clients); /* TODO: free all connections */ free (w->conns); /* free this workers memory */ worker_free (w); exit (0); }