+ st->task.pre_select = signal_pre_select;
+ st->task.post_select = signal_post_select;
+ sprintf(st->task.status, "signal task");
+
+ st->fd = para_signal_init(); /* always successful */
+
+ PARA_NOTICE_LOG("setting up signal handlers\n");
+ if (para_install_sighandler(SIGINT) < 0)
+ goto err;
+ if (para_install_sighandler(SIGTERM) < 0)
+ goto err;
+ if (para_install_sighandler(SIGHUP) < 0)
+ goto err;
+ if (para_install_sighandler(SIGCHLD) < 0)
+ goto err;
+ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
+ goto err;
+ add_close_on_fork_list(st->fd);
+ register_task(&st->task);
+ return;
+err:
+ PARA_EMERG_LOG("could not install signal handlers\n");
+ exit(EXIT_FAILURE);
+}
+
+static void command_pre_select(struct sched *s, struct task *t)
+{
+ struct server_command_task *sct = container_of(t, struct server_command_task, task);
+ para_fd_set(sct->listen_fd, &s->rfds, &s->max_fileno);
+}
+
+static void command_post_select(struct sched *s, struct task *t)
+{
+ struct server_command_task *sct = container_of(t, struct server_command_task, task);
+
+ int new_fd, ret, i;
+ char *peer_name;
+ pid_t child_pid;
+
+ if (!FD_ISSET(sct->listen_fd, &s->rfds))
+ return;
+ ret = para_accept(sct->listen_fd, NULL, 0);
+ if (ret < 0)
+ goto out;
+ new_fd = ret;
+ peer_name = remote_name(new_fd);
+ PARA_INFO_LOG("got connection from %s, forking\n", peer_name);
+ mmd->num_connects++;
+ mmd->active_connections++;
+ random();
+ child_pid = fork();
+ if (child_pid < 0) {
+ ret = -ERRNO_TO_PARA_ERROR(errno);
+ goto out;
+ }
+ if (child_pid) {
+ close(new_fd);
+ /* parent keeps accepting connections */
+ return;
+ }
+ alarm(ALARM_TIMEOUT);
+ close_listed_fds();
+ para_signal_shutdown();
+ /*
+ * put info on who we are serving into argv[0] to make
+ * client ip visible in top/ps
+ */
+ for (i = sct->argc - 1; i >= 0; i--)
+ memset(sct->argv[i], 0, strlen(sct->argv[i]));
+ sprintf(sct->argv[0], "para_server (serving %s)", peer_name);
+ return handle_connect(new_fd, peer_name);
+out:
+ if (ret < 0)
+ PARA_CRIT_LOG("%s\n", para_strerror(-ret));
+}
+
+static void init_server_command_task(int argc, char **argv)
+{
+ int ret;
+ static struct server_command_task server_command_task_struct,
+ *sct = &server_command_task_struct;
+
+ PARA_NOTICE_LOG("initializing tcp command socket\n");
+ sct->task.pre_select = command_pre_select;
+ sct->task.post_select = command_post_select;
+ sct->argc = argc;
+ sct->argv = argv;
+ ret = para_listen(AF_UNSPEC, IPPROTO_TCP, conf.port_arg);