Exemplo n.º 1
0
Arquivo: work.c Projeto: richo/juici2
void mainloop(int socket) {
    uint8_t butts[2048];
    int res, i;
    size_t rcvd;
    pid_t build;
    enum message_type msg_type;
    BuildRequest* msg;
    /* Allocate some handlers on the heap */
    fd_list **subscriptions;
    /* Be super pessimistic about how many pids we might see */
#define ___MAX_PIDS pow(sizeof(pid_t), 8)
    subscriptions = malloc(sizeof(fd_list) * ___MAX_PIDS);
    memset(subscriptions, 0, ___MAX_PIDS);
    fd_list *new_sub;
    fd_list *sub_node;
#undef ___MAX_PIDS
    /* Setup FD sets for monitoring */
    fd_set fds;
    fd_set rfds, wfds, efds;
    FD_ZERO(&fds); FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);

    FD_SET(socket, &fds);
    /* Block SIGCHLD set setup signalfd for monitoring */
    sigset_t signals;
    sigemptyset(&signals);
    sigaddset(&signals, SIGCHLD);
    /* Block sigchld */
    sigprocmask(SIG_BLOCK, &signals, NULL);
    /* Setup a signalfd */
#ifdef __linux
    int sigfd = signalfd(-1, &signals, SFD_NONBLOCK |
                                       SFD_CLOEXEC);
    struct signalfd_siginfo child;
    size_t child_read;
#elif __APPLE__
    int sigfd = kqueue();
    int kq_status;
    struct kevent ke, child;
    EV_SET(&ke, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
    i = kevent(sigfd, &ke, 1, NULL, 0, NULL);
    if (i == -1) {
        warn("Couldn't set up sigfd\n");
        return;
    }
#endif
    /* Add sigfd to the main set */
    FD_SET(sigfd, &fds);
    /* Structure to read children into */
    pid_t child_pid;
    int child_status;

    while(1) {
        FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);

        memcpy(&rfds, &fds, sizeof(fd_set));
        memcpy(&wfds, &fds, sizeof(fd_set));
        memcpy(&efds, &fds, sizeof(fd_set));

        res = select(FD_SETSIZE, &rfds, NULL, &efds, NULL);
        info("got %d fds\n", res);
        if (res == 0) {
            error("No fd's returned from select\n");
        } else if (res == -1) {
            warn("select call interrupted");
            break;
            // We probably saw a signal. Defer signals and do some stuff.
        } else {
            for (i = 0; i < FD_SETSIZE; ++i) {
                if (FD_ISSET(i, &efds)) {
                    debug("%d has made a whoopsie\n", i);
                }
                if (!FD_ISSET(i, &rfds))
                    continue;

                if (i == socket) {
                    accept_new_connection(socket, &fds);
                    info("Accepted a new connection\n");
                } else if (i == sigfd) {
                    child_status = 0;
#ifdef __linux
                    child_read = read(sigfd, &child, sizeof(child));
                    switch(child_read) {
                        case 0:
                        case -1:
                            warn("Couldn't read from signalfd");
                            continue;
                        default:
                            info("Recieved signal %d from %d\n",
                                    child.ssi_signo,
                                    child.ssi_pid);

                    }
                    if (child.ssi_signo == SIGCHLD) {
                        child_pid = waitpid(child.ssi_pid, &child_status, 0);
                        child_status = WEXITSTATUS(child_status);
                        info("Child %d exited with status %d\n", child_pid, child_status);
                        notify(subscriptions, child_pid, child_status);
                    }
#elif __APPLE__
                    kq_status = kevent(sigfd, NULL, 0, &child, 1, NULL);
                    if (kq_status == -1) {
                        warn("kevent read failed\n");
                        return;
                    }
                    info("Recieved signal %ld\n", child.ident);
                    child_pid = wait(&child_status);
                    child_status = WEXITSTATUS(child_status);
                    info("Child %d exited with status %d\n", child_pid, child_status);
                    notify(subscriptions, child_pid, child_status);
#endif
                } else {
                    // Check if the socket is still alive
                    if (recv(i, butts, 1, MSG_PEEK) < 1) {
                        close(i);
                        FD_CLR(i, &fds);
                        continue;
                    }

                    msg_type = load_message_type(i);
                    switch(msg_type) {
                        case MSG_ERROR:
                            /* Connection is irreperably damaged */
                            error("Couldn't decode message type\n");
                            close(i);
                            FD_CLR(i, &fds);
                            break;
                        case MSG_BUILD_REQUEST:
                            msg = load_request(i);
                            if (!msg) {
                                info("Got a null request from %d\n", i);
                                continue;
                            }
                            info("new payload\n");
                            info(" command  : %s\n", msg->command);
                            info(" workspace: %s\n", msg->workspace);
                            info(" priority : %d\n", msg->priority);
                            info("--\n");
                            if (init_worktree2(msg->workspace) != 0) {
                                /* TODO: Actually bail out of this */
                                error("Couldn't create worktree %s\n", msg->workspace);
                            }
                            build = start_build(msg);
                            info("Started a new build from %d with pid %d\n", i, build);
                            build_request__free_unpacked(msg, NULL);
                            /* Implicitly subscribe whoever kicked off the build */
                            new_sub = malloc(sizeof(fd_list));
                            new_sub->fd = i;
                            new_sub->next = NULL;
                            if (subscriptions[build] == NULL) {
                                subscriptions[build] = new_sub;
                            } else {
                                sub_node = subscriptions[build];
                                while (sub_node != NULL) {
                                    sub_node = sub_node->next;
                                }
                                sub_node->next = new_sub;
                            }
                            /* TODO: Write out the pid + a nonce to the client.
                             * TODO: Implement an implicit subscribe flag in the build request
                             */
                            break;
                        default:
                            error("Unknown message type %d\n", msg_type);
                    }
                }
            }
        }
    }
}
Exemplo n.º 2
0
void CServer::handle_request(const char *request)
{
	const char *p;
	int cmd_len;
	int ok;

	logger->log(3, "Got request: %s", request);
	p = strchr(request,' ');
	if (p == 0) {
		p = request + strlen(request);
	}
	cmd_len = p - request;
	while (*p == ' ') {
		p++;
	}
	ok = 0;
	if (cmd_len == 0) {
		logger->log(2, "Empty request!");
		return;
	}
	char *command = new char[cmd_len+1];
	memcpy(command, request, cmd_len);
	command[cmd_len] = 0;
	try {
		if (strcmp(command, "SEARCH") == 0) {
			ok = 1;
			search_request(p);
		}
		if (strcmp(command, "COUNT") == 0) {
			ok = 1;
			count_request();
		}
		if (strcmp(command, "DELETEHOST") == 0) {
			ok = 1;
			delete_request(p);
		}
		if (strcmp(command, "LOAD") == 0) {
			ok = 1;
			load_request(p);
		}
		if (strcmp(command, "STATUS") == 0) {
			ok = 1;
			status_request();
		}
		if (strcmp(command, "HOSTINFO") == 0) {
			ok = 1;
			host_info_request(p);
		}
		if (strcmp(command, "HOSTSTAT") == 0) {
			ok = 1;
			host_stat_request(p);
		}
		if (strcmp(command, "CACHEINFO") == 0) {
			ok = 1;
			cache_info_request();
		}
		if (strcmp(command, "UPDATEHOSTS") == 0) {
			ok = 1;
			update_hosts_request(p);
		}
		if (strcmp(command, "SERVERSTAT") == 0) {
			ok = 1;
			server_stat_request();
		}
		if (strcmp(command, "DEBUG") == 0) {
			ok = 1;
			debug_request(p);
		}
		if (strcmp(command, "DUMP") == 0) {
			ok = 1;
			dump_state_request();
		}
		if (strcmp(command, "FULLSCAN") == 0) {
			ok = 1;
			enable_full_request(p);
		}
		if (strcmp(command, "WORDORDER") == 0) {
			ok = 1;
			word_order_request();
		}
		if (strcmp(command, "CLEARPAGECACHE") == 0) {
			ok = 1;
			clear_pagecache_request();
		}
		if (strcmp(command, "CLEARQUERYCACHE") == 0) {
			ok = 1;
			clear_querycache_request();
		}
		if (strcmp(command, "DUMPFILES") == 0) {
			ok = 1;
			dump_files_request(p);
		}
		if (strcmp(command, "DUMPINDEX") == 0) {
			ok = 1;
			dump_index_request(p);
		}
		if (!ok) {
			throw std::runtime_error(std::string("Unrecognized request: ") + request);
		}
	}
	catch (std::runtime_error &e) {
		logger->log(1, "Error: %s", e.what());
		send_string("ERROR");
	}
	delete[] command;	
	m_request_count++;
}