static void process_write_frontend(struct conn_context *ctx) { int front_fd; char *buf; int data_len; int cpu_id; int ret; cpu_id = ctx->cpu_id; front_fd = ctx->fd; buf = ctx->buf; data_len = ctx->data_len; if (ctx->flags & PROXY_BACKEND_EVENT) { printf("Write to front end socket while back end socket enabled\n"); goto free_back; } ret = write(front_fd, buf, data_len); if (ret < 0) { perror("Can't write front-end socket"); goto free_back; } print_d("Write %d to front end socket %d\n", data_len, front_fd); wdata[cpu_id].trancnt++; free_back: process_close(ctx); free_context(ctx); return; }
static void process_write_backend(struct conn_context *ctx) { int ep_fd, end_fd; int events = ctx->events; char *buf; int data_len; int ret; ep_fd = ctx->ep_fd; end_fd = ctx->end_fd; buf = ctx->buf; data_len = ctx->data_len; print_d("Process write event[%02x] on back-end socket %d\n", events, end_fd); if (events & (EPOLLHUP | EPOLLERR)) { printf("process_write_backend() with events HUP or ERR 0x%x\n", events); goto free_back; } struct epoll_event evt; if (!(ctx->flags & PROXY_BACKEND_EVENT)) { printf("Write to back-end socket while back end socket not enabled\n"); goto free_back; } ret = write(end_fd, buf, data_len); if (ret < 0) { perror("process_write() can't write back end socket"); goto free_back; } print_d("Write %d to back-end socket %d\n", ret, end_fd); ctx->handler = process_read_backend; ctx->flags |= PROXY_BACKEND_EVENT; evt.events = EPOLLIN | EPOLLHUP | EPOLLERR; evt.data.ptr = ctx; ret = epoll_ctl(ep_fd, EPOLL_CTL_MOD, end_fd, &evt); if (ret < 0) { perror("Unable to add client socket read event to epoll"); goto free_back; } goto back; free_back: process_close(ctx); free_context(ctx); back: return; }
static void process_write(struct conn_context *client_ctx) { int ep_fd, fd; int events = client_ctx->events; int cpu_id = client_ctx->cpu_id; int ret; struct epoll_event evt; ep_fd = client_ctx->ep_fd; fd = client_ctx->fd; print_d("Process write event[%02x]\n", events); if (events & (EPOLLHUP | EPOLLERR)) { printf("process_write() with events HUP or ERR\n"); goto free_back; } ret = write(fd, http_response, http_response_len); if (ret < 0) { wdata[cpu_id].write_cnt++; perror("process_write() can't write client socket"); goto free_back; } print_d("Write %d to socket %d\n", ret, fd); wdata[cpu_id].trancnt++; if (!enable_keepalive) goto free_back; client_ctx->handler = process_read; evt.events = EPOLLIN | EPOLLHUP | EPOLLERR; evt.data.ptr = client_ctx; ret = epoll_ctl(ep_fd, EPOLL_CTL_MOD, fd, &evt); if (ret < 0) { perror("Unable to add client socket read event to epoll"); goto free_back; } goto back; free_back: process_close(client_ctx); free_context(client_ctx); back: return; }
static gboolean process_and_relay_close (CockpitWebService *self, CockpitSocket *socket, const gchar *channel, GBytes *payload) { gboolean valid; valid = process_close (self, socket, channel); if (valid && !self->sent_done) cockpit_transport_send (self->transport, NULL, payload); return valid; }
//SIGINT and SIGTERM signal handler static void quit(int sig) { //let all the processes continue if stopped struct list_node *node = NULL; for (node=pf.members.first; node!= NULL; node=node->next) { struct process *p = (struct process*)(node->data); kill(p->pid, SIGCONT); process_close(p); } //free all the memory cleanup_process_family(&pf); //fix ^C little problem printf("\r"); fflush(stdout); exit(0); }
/// Iterates the table, sending SIGTERM to stopped jobs and SIGKILL to those /// that didn't die from SIGTERM after a while(exit_timeout is 0). static void job_stop_timer_cb(uv_timer_t *handle) { Job *job; uint64_t now = os_hrtime(); for (size_t i = 0; i < MAX_RUNNING_JOBS; i++) { if ((job = table[i]) == NULL || !job->stopped_time) { continue; } uint64_t elapsed = now - job->stopped_time; if (!job->term_sent && elapsed >= TERM_TIMEOUT) { ILOG("Sending SIGTERM to job(id: %d)", job->id); uv_kill(job->pid, SIGTERM); job->term_sent = true; } else if (elapsed >= KILL_TIMEOUT) { ILOG("Sending SIGKILL to job(id: %d)", job->id); uv_kill(job->pid, SIGKILL); process_close(job); } } }
static void chld_handler(uv_signal_t *handle, int signum) { int stat = 0; int pid; do { pid = waitpid(-1, &stat, WNOHANG); } while (pid < 0 && errno == EINTR); if (pid <= 0) { return; } if (WIFSTOPPED(stat) || WIFCONTINUED(stat)) { // Only care for processes that exited return; } Job *job = NULL; // find the job corresponding to the exited pid for (int i = 0; i < MAX_RUNNING_JOBS; i++) { if ((job = table[i]) != NULL && job->pid == pid) { if (WIFEXITED(stat)) { job->status = WEXITSTATUS(stat); } else if (WIFSIGNALED(stat)) { job->status = WTERMSIG(stat); } if (exiting) { // don't enqueue more events when exiting process_close(job); } else { event_push((Event) {.handler = job_exited, .data = job}, false); } break; } }
void SFTP::process(void) { const u_int msg_len = buffer_get_int (&iqueue); const u_int type = buffer_get_char(&iqueue); switch (type) { case SSH2_FXP_INIT: process_init(); break; case SSH2_FXP_OPEN: process_open(); break; case SSH2_FXP_CLOSE: process_close(); break; case SSH2_FXP_READ: process_read(); break; case SSH2_FXP_WRITE: process_write(); break; case SSH2_FXP_LSTAT: process_lstat(); break; case SSH2_FXP_FSTAT: process_fstat(); break; case SSH2_FXP_SETSTAT: process_setstat(); break; case SSH2_FXP_FSETSTAT: process_fsetstat(); break; case SSH2_FXP_OPENDIR: process_opendir(); break; case SSH2_FXP_READDIR: process_readdir(); break; case SSH2_FXP_REMOVE: process_remove(); break; case SSH2_FXP_MKDIR: process_mkdir(); break; case SSH2_FXP_RMDIR: process_rmdir(); break; case SSH2_FXP_REALPATH: process_realpath(); break; case SSH2_FXP_STAT: process_stat(); break; case SSH2_FXP_RENAME: process_rename(); break; case SSH2_FXP_READLINK: process_readlink(); break; case SSH2_FXP_SYMLINK: process_symlink(); break; case SSH2_FXP_EXTENDED: process_extended(); break; default: error("Unknown message %d", type); break; } /* discard the remaining bytes from the current packet */ if (msg_len < buffer_len(&iqueue)) { error("iqueue grew unexpectedly"); sftp_server_cleanup_exit(255); } u_int consumed = msg_len - buffer_len(&iqueue); if (msg_len < consumed) { error("msg_len %d < consumed %d", msg_len, consumed); sftp_server_cleanup_exit(255); } if (msg_len > consumed) buffer_consume(&iqueue, msg_len - consumed); }
// Opens a library and returns a handle static struct MuLibrary* sh_open (struct MuLoader* self, const char* path, MuError** err) { ShLibrary* library = NULL; Process handle; array* tests = NULL; char* line = NULL; char* dot = NULL; unsigned int len; struct stat statbuf; /* As a sanity check, make sure the file is actually valid */ if (stat(path, &statbuf) != 0) { MU_RAISE_GOTO(error, err, MU_ERROR_LOAD_LIBRARY, "%s: %s", path, strerror(errno)); } if (!S_ISREG(statbuf.st_mode)) { MU_RAISE_GOTO(error, err, MU_ERROR_LOAD_LIBRARY, "%s: not a file", path); } library = calloc(1, sizeof(ShLibrary)); library->base.loader = self; library->path = strdup(path); library->name = strdup(basename_pure(path)); dot = strrchr(library->name, '.'); if (dot) { *dot = '\0'; } mu_sh_exec(&handle, path, "mu_enum_test_functions >& ${MU_CMD_OUT}"); while ((len = process_channel_read_line(&handle, 4, &line))) { ShTest* test = calloc(1, sizeof(ShTest)); char* div1, *div2; line[len-1] = '\0'; div1 = strchr(line, '_'); div2 = strchr(div1+1, '_'); if (div1 && div2) { test->base.loader = self; test->base.library = (MuLibrary*) library; test->function = strdup(line); *div1 = *div2 = '\0'; test->suite = strdup(div1+1); test->name = strdup(div2+1); tests = array_append(tests, test); } free(line); } process_close(&handle); library->tests = (ShTest**) tests; error: return (MuLibrary*) library; }
static void process_accept(struct conn_context * listen_ctx) { int client_fd, listen_fd; int events = listen_ctx->events; struct epoll_event evt; struct context_pool *pool; struct conn_context *client_ctx; int cpu_id = listen_ctx->cpu_id; int ret = 0; int i; listen_fd = listen_ctx->fd; //TODO: What else should I do. if (events & (EPOLLHUP | EPOLLERR)) return; for (i = 0; i < ACCEPT_PER_LISTEN_EVENT; i++) { int flags; client_fd = accept(listen_fd, NULL, NULL); if (client_fd < 0) { wdata[cpu_id].accept_cnt++; goto back; } flags = fcntl(client_fd, F_GETFL, 0); flags |= O_NONBLOCK; fcntl(client_fd, F_SETFL, flags); print_d("Accept socket %d from %d\n", client_fd, listen_fd); } pool = listen_ctx->pool; client_ctx = alloc_context(pool); assert(client_ctx); client_ctx->fd = client_fd; if (enable_proxy) client_ctx->handler = process_read_frontend; else client_ctx->handler = process_read; client_ctx->cpu_id = listen_ctx->cpu_id; client_ctx->ep_fd = listen_ctx->ep_fd; evt.events = EPOLLIN | EPOLLHUP | EPOLLERR; evt.data.ptr = client_ctx; ret = epoll_ctl(client_ctx->ep_fd, EPOLL_CTL_ADD, client_ctx->fd, &evt); if (ret < 0) { perror("Unable to add client socket read event to epoll"); goto free_back; } client_ctx->fd_added = 1; goto back; free_back: print_d("cpu[%d] close socket %d\n", cpu_id, client_ctx->fd); process_close(client_ctx); free_context(client_ctx); back: return; }
static void process_read(struct conn_context *client_ctx) { int ep_fd, fd; int events = client_ctx->events; struct epoll_event evt; int ret; char *buf = client_ctx->buf; int cpu_id = client_ctx->cpu_id; ep_fd = client_ctx->ep_fd; fd = client_ctx->fd; //FIXME: What else should I do. if (events & EPOLLHUP) { print_d("process_read() with events HUP\n"); goto free_back; } if (events & EPOLLERR) { print_d("process_read() with events ERR\n"); goto free_back; } print_d("Process read event[%02x] on socket %d\n", events, fd); ret = read(fd, buf, MAX_BUFSIZE); if (ret < 0) { wdata[cpu_id].read_cnt++; perror("process_read() can't read client socket"); goto free_back; } else if (ret == 0) { goto free_back; print_d("Socket %d is closed\n", fd); } client_ctx->data_len = ret; print_d("Read %d from socket %d\n", ret, fd); client_ctx->handler = process_write; evt.events = EPOLLOUT | EPOLLHUP | EPOLLERR; evt.data.ptr = client_ctx; ret = epoll_ctl(ep_fd, EPOLL_CTL_MOD, fd, &evt); if (ret < 0) { perror("Unable to add client socket read event to epoll"); goto free_back; } goto back; free_back: print_d("cpu[%d] close socket %d\n", cpu_id, client_ctx->fd); process_close(client_ctx); free_context(client_ctx); back: return; }
static void process_read_frontend(struct conn_context *ctx) { int ep_fd, front_fd, end_fd; char *buf = ctx->buf; int events = ctx->events; struct epoll_event evt; struct sockaddr_in addr_in; int ret; int cpu_id = ctx->cpu_id; ep_fd = ctx->ep_fd; front_fd = ctx->fd; //FIXME: What else should I do. if (events & (EPOLLHUP | EPOLLERR)) { printf("process_read_frontend() with events HUP or ERR\n"); goto free_back; } print_d("Process read event[%02x] on front-end socket %d\n", events, front_fd); ret = read(front_fd, buf, MAX_BUFSIZE); if (ret < 0) { wdata[cpu_id].read_cnt++; perror("process_read_frontend() can't read client socket"); goto free_back; } ctx->data_len = ret; print_d("Read %d from front-end socket %d\n", ret, front_fd); //Remove interested read event for front-end socket evt.events = EPOLLHUP | EPOLLERR; evt.data.ptr = ctx; ret = epoll_ctl(ep_fd, EPOLL_CTL_MOD, front_fd, &evt); if (ret < 0) { perror("Unable to add client socket read event to epoll"); goto free_back; } int flags; ret = socket(AF_INET, SOCK_STREAM, 0); if (ret < 0) { perror("Unable to create new socket for backend"); goto free_back; } end_fd = ret; ctx->end_fd = end_fd; print_d("Create socket %d\n", ret); flags = fcntl(ret, F_GETFL, 0); flags |= O_NONBLOCK; fcntl(ret, F_SETFL, flags); struct linger ling = {1, 0}; ret = setsockopt(end_fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling)); if (ret < 0) { perror("Unable to set socket linger option"); goto free_back; } select_backend(&addr_in); ret = connect(end_fd, (struct sockaddr *)&addr_in, sizeof(struct sockaddr)); if (ret < 0) { if (errno != EINPROGRESS) { perror("Unable to connect to back end server"); goto free_back; } } ctx->handler = process_write_backend; ctx->flags |= PROXY_BACKEND_EVENT; evt.events = EPOLLOUT | EPOLLHUP | EPOLLERR; evt.data.ptr = ctx; ret = epoll_ctl(ep_fd, EPOLL_CTL_ADD, end_fd, &evt); if (ret < 0) { perror("Unable to add client socket read event to epoll"); goto free_back; } ctx->end_fd_added = 1; print_d("Add back-end socket %d to epoll\n", end_fd); goto back; free_back: print_d("cpu[%d] close socket %d\n", cpu_id, ctx->fd); process_close(ctx); free_context(ctx); back: return; }
static void process_read_backend(struct conn_context *ctx) { int front_fd, end_fd, ep_fd; char *buf; int cpu_id; struct epoll_event evt; int ret; cpu_id = ctx->cpu_id; ep_fd = ctx->ep_fd; end_fd = ctx->end_fd; front_fd = ctx->fd; buf = ctx->buf; if (!(ctx->flags & PROXY_BACKEND_EVENT)) { printf("Process back end read while backend socket not enable\n"); goto free_back; } ret = read(end_fd, buf, MAX_BUFSIZE); if (ret < 0) { wdata[cpu_id].read_cnt++; perror("process_read_backend() can't read client socket"); goto free_back; } print_d("Read %d from back end socket %d\n", ret, end_fd); ctx->handler = process_write_frontend; ctx->flags &= ~PROXY_BACKEND_EVENT; ctx->data_len = ret; evt.events = EPOLLOUT | EPOLLHUP | EPOLLERR; evt.data.ptr = ctx; ret = epoll_ctl(ep_fd, EPOLL_CTL_MOD, front_fd, &evt); if (ret < 0) { perror("Unable to add client socket read event to epoll"); goto free_back; } evt.events = EPOLLHUP | EPOLLERR; evt.data.ptr = ctx; //FIXME: Why monitor end fd? ret = epoll_ctl(ep_fd, EPOLL_CTL_MOD, end_fd, &evt); if (ret < 0) { perror("Unable to add client socket read event to epoll"); goto free_back; } goto back; free_back: process_close(ctx); free_context(ctx); back: return; }
static void process(void) { u_int msg_len; u_int buf_len; u_int consumed; u_int type; u_char *cp; buf_len = buffer_len(&iqueue); if (buf_len < 5) return; /* Incomplete message. */ cp = buffer_ptr(&iqueue); msg_len = get_u32(cp); if (msg_len > SFTP_MAX_MSG_LENGTH) { error("bad message from %s local user %s", client_addr, pw->pw_name); sftp_server_cleanup_exit(11); } if (buf_len < msg_len + 4) return; buffer_consume(&iqueue, 4); buf_len -= 4; type = buffer_get_char(&iqueue); switch (type) { case SSH2_FXP_INIT: process_init(); break; case SSH2_FXP_OPEN: process_open(); break; case SSH2_FXP_CLOSE: process_close(); break; case SSH2_FXP_READ: process_read(); break; case SSH2_FXP_WRITE: process_write(); break; case SSH2_FXP_LSTAT: process_lstat(); break; case SSH2_FXP_FSTAT: process_fstat(); break; case SSH2_FXP_SETSTAT: process_setstat(); break; case SSH2_FXP_FSETSTAT: process_fsetstat(); break; case SSH2_FXP_OPENDIR: process_opendir(); break; case SSH2_FXP_READDIR: process_readdir(); break; case SSH2_FXP_REMOVE: process_remove(); break; case SSH2_FXP_MKDIR: process_mkdir(); break; case SSH2_FXP_RMDIR: process_rmdir(); break; case SSH2_FXP_REALPATH: process_realpath(); break; case SSH2_FXP_STAT: process_stat(); break; case SSH2_FXP_RENAME: process_rename(); break; case SSH2_FXP_READLINK: process_readlink(); break; case SSH2_FXP_SYMLINK: process_symlink(); break; case SSH2_FXP_EXTENDED: process_extended(); break; default: error("Unknown message %d", type); break; } /* discard the remaining bytes from the current packet */ if (buf_len < buffer_len(&iqueue)) { error("iqueue grew unexpectedly"); sftp_server_cleanup_exit(255); } consumed = buf_len - buffer_len(&iqueue); if (msg_len < consumed) { error("msg_len %d < consumed %d", msg_len, consumed); sftp_server_cleanup_exit(255); } if (msg_len > consumed) buffer_consume(&iqueue, msg_len - consumed); }
/// Tries to start a new job. /// /// @param[out] status The job id if the job started successfully, 0 if the job /// table is full, -1 if the program could not be executed. /// @return The job pointer if the job started successfully, NULL otherwise Job *job_start(JobOptions opts, int *status) { int i; Job *job; // Search for a free slot in the table for (i = 0; i < MAX_RUNNING_JOBS; i++) { if (table[i] == NULL) { break; } } if (i == MAX_RUNNING_JOBS) { // No free slots shell_free_argv(opts.argv); *status = 0; return NULL; } job = xmalloc(sizeof(Job)); // Initialize job->id = i + 1; *status = job->id; job->status = -1; job->refcount = 1; job->stopped_time = 0; job->term_sent = false; job->in = NULL; job->out = NULL; job->err = NULL; job->opts = opts; job->closed = false; process_init(job); if (opts.writable) { handle_set_job((uv_handle_t *)job->proc_stdin, job); job->refcount++; } if (opts.stdout_cb) { handle_set_job((uv_handle_t *)job->proc_stdout, job); job->refcount++; } if (opts.stderr_cb) { handle_set_job((uv_handle_t *)job->proc_stderr, job); job->refcount++; } // Spawn the job if (!process_spawn(job)) { if (opts.writable) { uv_close((uv_handle_t *)job->proc_stdin, close_cb); } if (opts.stdout_cb) { uv_close((uv_handle_t *)job->proc_stdout, close_cb); } if (opts.stderr_cb) { uv_close((uv_handle_t *)job->proc_stderr, close_cb); } process_close(job); event_poll(0); // Manually invoke the close_cb to free the job resources *status = -1; return NULL; } if (opts.writable) { job->in = wstream_new(opts.maxmem); wstream_set_stream(job->in, job->proc_stdin); } // Start the readable streams if (opts.stdout_cb) { job->out = rstream_new(read_cb, rbuffer_new(JOB_BUFFER_SIZE), job); rstream_set_stream(job->out, job->proc_stdout); rstream_start(job->out); } if (opts.stderr_cb) { job->err = rstream_new(read_cb, rbuffer_new(JOB_BUFFER_SIZE), job); rstream_set_stream(job->err, job->proc_stderr); rstream_start(job->err); } // Save the job to the table table[i] = job; return job; }
static void job_exited(Event event) { Job *job = event.data; process_close(job); }
static gboolean on_transport_control (CockpitTransport *transport, const gchar *command, const gchar *channel, JsonObject *options, GBytes *payload, gpointer user_data) { const gchar *problem = "protocol-error"; CockpitWebService *self = user_data; CockpitSocket *socket = NULL; gboolean valid = FALSE; gboolean forward; if (!channel) { if (g_strcmp0 (command, "init") == 0) { problem = process_transport_init (self, transport, options); valid = (problem == NULL); } else if (!self->init_received) { g_message ("bridge did not send 'init' message first"); valid = FALSE; } else if (g_strcmp0 (command, "authorize") == 0) { valid = process_transport_authorize (self, transport, options); } else { g_debug ("received a %s unknown control command", command); valid = TRUE; } } else { socket = cockpit_socket_lookup_by_channel (&self->sockets, channel); /* Usually all control messages with a channel are forwarded */ forward = TRUE; if (g_strcmp0 (command, "close") == 0) { valid = process_close (self, socket, channel); } else { valid = TRUE; } if (forward) { /* Forward this message to the right websocket */ if (socket && web_socket_connection_get_ready_state (socket->connection) == WEB_SOCKET_STATE_OPEN) { web_socket_connection_send (socket->connection, WEB_SOCKET_DATA_TEXT, self->control_prefix, payload); } } } if (!valid) { outbound_protocol_error (self, transport, problem); } return TRUE; /* handled */ }
static void process(void) { u_int msg_len; u_int buf_len; u_int consumed; u_int type; u_char *cp; buf_len = buffer_len(&iqueue); if (buf_len < 5) return; /* Incomplete message. */ cp = buffer_ptr(&iqueue); msg_len = GET_32BIT(cp); if (msg_len > 256 * 1024) { error("bad message "); exit(11); } if (buf_len < msg_len + 4) return; buffer_consume(&iqueue, 4); buf_len -= 4; type = buffer_get_char(&iqueue); switch (type) { case SSH2_FXP_INIT: process_init(); break; case SSH2_FXP_OPEN: process_open(); break; case SSH2_FXP_CLOSE: process_close(); break; case SSH2_FXP_READ: process_read(); break; case SSH2_FXP_WRITE: process_write(); break; case SSH2_FXP_LSTAT: process_lstat(); break; case SSH2_FXP_FSTAT: process_fstat(); break; case SSH2_FXP_SETSTAT: process_setstat(); break; case SSH2_FXP_FSETSTAT: process_fsetstat(); break; case SSH2_FXP_OPENDIR: process_opendir(); break; case SSH2_FXP_READDIR: process_readdir(); break; case SSH2_FXP_REMOVE: process_remove(); break; case SSH2_FXP_MKDIR: process_mkdir(); break; case SSH2_FXP_RMDIR: process_rmdir(); break; case SSH2_FXP_REALPATH: process_realpath(); break; case SSH2_FXP_STAT: process_stat(); break; case SSH2_FXP_RENAME: process_rename(); break; case SSH2_FXP_READLINK: process_readlink(); break; case SSH2_FXP_SYMLINK: process_symlink(); break; case SSH2_FXP_EXTENDED: process_extended(); break; default: error("Unknown message %d", type); break; } /* discard the remaining bytes from the current packet */ if (buf_len < buffer_len(&iqueue)) fatal("iqueue grows"); consumed = buf_len - buffer_len(&iqueue); if (msg_len < consumed) fatal("msg_len %d < consumed %d", msg_len, consumed); if (msg_len > consumed) buffer_consume(&iqueue, msg_len - consumed); }
/** * Deletes this process manager. */ virtual ~Process() { StackTrace trace(__METHOD__, __FILE__, __LINE__); if (_handle) { process_close(_handle); } }