server: attempt to handle client ctrl-c

Signed-off-by: Jens Axboe <axboe@kernel.dk>
diff --git a/client.c b/client.c
index d81f755..e6b51d3 100644
--- a/client.c
+++ b/client.c
@@ -118,12 +118,46 @@
 	return 0;
 }
 
+void fio_clients_terminate(void)
+{
+	struct flist_head *entry;
+	struct fio_client *client;
+
+	flist_for_each(entry, &client_list) {
+		client = flist_entry(entry, struct fio_client, list);
+
+		fio_net_send_simple_cmd(client->fd, FIO_NET_CMD_QUIT, 0);
+	}
+}
+
+static void sig_int(int sig)
+{
+	fio_clients_terminate();
+}
+
+static void client_signal_handler(void)
+{
+	struct sigaction act;
+
+	memset(&act, 0, sizeof(act));
+	act.sa_handler = sig_int;
+	act.sa_flags = SA_RESTART;
+	sigaction(SIGINT, &act, NULL);
+
+	memset(&act, 0, sizeof(act));
+	act.sa_handler = sig_int;
+	act.sa_flags = SA_RESTART;
+	sigaction(SIGTERM, &act, NULL);
+}
+
 int fio_clients_connect(void)
 {
 	struct fio_client *client;
 	struct flist_head *entry, *tmp;
 	int ret;
 
+	client_signal_handler();
+
 	flist_for_each_safe(entry, tmp, &client_list) {
 		client = flist_entry(entry, struct fio_client, list);
 
diff --git a/fio.c b/fio.c
index 1074606..d1faaca 100644
--- a/fio.c
+++ b/fio.c
@@ -75,7 +75,6 @@
 
 struct io_log *agg_io_log[2];
 
-#define TERMINATE_ALL		(-1)
 #define JOB_START_TIMEOUT	(5 * 1000)
 
 void td_set_runstate(struct thread_data *td, int runstate)
@@ -88,7 +87,7 @@
 	td->runstate = runstate;
 }
 
-static void terminate_threads(int group_id)
+void fio_terminate_threads(int group_id)
 {
 	struct thread_data *td;
 	int i;
@@ -126,7 +125,7 @@
 		exit_backend = 1;
 		fflush(stdout);
 		exit_value = 128;
-		terminate_threads(TERMINATE_ALL);
+		fio_terminate_threads(TERMINATE_ALL);
 	}
 }
 
@@ -184,6 +183,13 @@
 	act.sa_handler = sig_int;
 	act.sa_flags = SA_RESTART;
 	sigaction(SIGTERM, &act, NULL);
+
+	if (is_backend) {
+		memset(&act, 0, sizeof(act));
+		act.sa_handler = sig_int;
+		act.sa_flags = SA_RESTART;
+		sigaction(SIGPIPE, &act, NULL);
+	}
 }
 
 /*
@@ -750,7 +756,7 @@
 		if (!in_ramp_time(td) && should_check_rate(td, bytes_done)) {
 			if (check_min_rate(td, &comp_time, bytes_done)) {
 				if (exitall_on_terminate)
-					terminate_threads(td->groupid);
+					fio_terminate_threads(td->groupid);
 				td_verror(td, EIO, "check_min_rate");
 				break;
 			}
@@ -1265,7 +1271,7 @@
 		exec_string(td->o.exec_postrun);
 
 	if (exitall_on_terminate)
-		terminate_threads(td->groupid);
+		fio_terminate_threads(td->groupid);
 
 err:
 	if (td->error)
@@ -1419,7 +1425,7 @@
 	}
 
 	if (*nr_running == cputhreads && !pending && realthreads)
-		terminate_threads(TERMINATE_ALL);
+		fio_terminate_threads(TERMINATE_ALL);
 }
 
 static void *gtod_thread_main(void *data)
@@ -1481,6 +1487,8 @@
 	if (fio_gtod_offload && fio_start_gtod_thread())
 		return;
 
+	set_sig_handlers();
+
 	if (!terse_output) {
 		log_info("Starting ");
 		if (nr_thread)
@@ -1496,8 +1504,6 @@
 		fflush(stdout);
 	}
 
-	set_sig_handlers();
-
 	todo = thread_number;
 	nr_running = 0;
 	nr_started = 0;
@@ -1613,7 +1619,7 @@
 			dprint(FD_MUTEX, "wait on startup_mutex\n");
 			if (fio_mutex_down_timeout(startup_mutex, 10)) {
 				log_err("fio: job startup hung? exiting.\n");
-				terminate_threads(TERMINATE_ALL);
+				fio_terminate_threads(TERMINATE_ALL);
 				fio_abort = 1;
 				nr_started--;
 				break;
@@ -1687,6 +1693,10 @@
 
 	while (nr_running) {
 		reap_threads(&nr_running, &t_rate, &m_rate);
+
+		if (is_backend)
+			fio_server_idle_loop();
+
 		usleep(10000);
 	}
 
diff --git a/fio.h b/fio.h
index fdc2c7e..a74fb10 100644
--- a/fio.h
+++ b/fio.h
@@ -575,6 +575,8 @@
 };
 
 extern void td_set_runstate(struct thread_data *, int);
+#define TERMINATE_ALL		(-1)
+extern void fio_terminate_threads(int);
 
 /*
  * Memory helpers
diff --git a/server.c b/server.c
index 93f5d8e..d0ff25a 100644
--- a/server.c
+++ b/server.c
@@ -120,6 +120,30 @@
 	void *pdu = NULL;
 
 	do {
+		struct pollfd pfd;
+
+		pfd.fd = sk;
+		pfd.events = POLLIN;
+		ret = 0;
+		do {
+			ret = poll(&pfd, 1, 100);
+			if (ret < 0) {
+				log_err("fio: poll: %s\n", strerror(errno));
+				break;
+			} else if (!ret)
+				continue;
+
+			if (pfd.revents & POLLIN)
+				break;
+			if (pfd.revents & (POLLERR|POLLHUP)) {
+				ret = 1;
+				break;
+			}
+		} while (ret >= 0);
+
+		if (ret < 0)
+			break;
+
 		ret = fio_recv_data(sk, &cmd, sizeof(cmd));
 		if (ret)
 			break;
@@ -168,9 +192,7 @@
 	if (ret) {
 		free(cmdret);
 		cmdret = NULL;
-	}
-
-	if (cmdret)
+	} else if (cmdret)
 		cmdret->flags &= ~FIO_NET_CMD_F_MORE;
 
 	return cmdret;
@@ -216,7 +238,7 @@
 	return ret;
 }
 
-static int send_simple_command(int sk, uint16_t opcode, uint64_t serial)
+int fio_net_send_simple_cmd(int sk, uint16_t opcode, uint64_t serial)
 {
 	struct fio_net_cmd cmd = {
 		.version	= __cpu_to_le16(FIO_SERVER_VER1),
@@ -229,29 +251,10 @@
 	return fio_send_data(sk, &cmd, sizeof(cmd));
 }
 
-/*
- * Send an ack for this command
- */
-static int ack_command(int sk, struct fio_net_cmd *cmd)
-{
-#if 0
-	return send_simple_command(sk, FIO_NET_CMD_ACK, cmd->serial);
-#else
-	return 0;
-#endif
-}
-
-#if 0
-static int nak_command(int sk, struct fio_net_cmd *cmd)
-{
-	return send_simple_command(sk, FIO_NET_CMD_NAK, cmd->serial);
-}
-#endif
-
 static int send_quit_command(void)
 {
 	dprint(FD_NET, "server: sending quit\n");
-	return send_simple_command(server_fd, FIO_NET_CMD_QUIT, 0);
+	return fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_QUIT, 0);
 }
 
 static int handle_cur_job(struct fio_net_cmd *cmd)
@@ -274,6 +277,7 @@
 
 	switch (cmd->opcode) {
 	case FIO_NET_CMD_QUIT:
+		fio_terminate_threads(TERMINATE_ALL);
 		return 1;
 	case FIO_NET_CMD_EXIT:
 		exit_backend = 1;
@@ -306,10 +310,6 @@
 			break;
 		}
 
-		ret = ack_command(sk, cmd);
-		if (ret)
-			break;
-
 		ret = handle_command(cmd);
 		if (ret)
 			break;
@@ -324,6 +324,12 @@
 	return ret;
 }
 
+void fio_server_idle_loop(void)
+{
+	if (server_fd != -1)
+		handle_connection(server_fd);
+}
+
 static int accept_loop(int listen_sk)
 {
 	struct sockaddr addr;
@@ -364,8 +370,12 @@
 
 	server_fd = sk;
 
+	printf("handle\n");
+
 	exitval = handle_connection(sk);
 
+	printf("out, exit %d\n", exitval);
+
 	server_fd = -1;
 	close(sk);
 
diff --git a/server.h b/server.h
index 431ae9e..61b61f3 100644
--- a/server.h
+++ b/server.h
@@ -57,12 +57,14 @@
 extern int fio_server_text_output(const char *, unsigned int len);
 extern int fio_server_log(const char *format, ...);
 extern int fio_net_send_cmd(int, uint16_t, const void *, off_t);
+extern int fio_net_send_simple_cmd(int sk, uint16_t opcode, uint64_t serial);
 
 struct thread_stat;
 struct group_run_stats;
 extern void fio_server_send_ts(struct thread_stat *, struct group_run_stats *);
 extern void fio_server_send_gs(struct group_run_stats *);
 extern void fio_server_send_status(void);
+extern void fio_server_idle_loop(void);
 
 extern int fio_clients_connect(void);
 extern int fio_clients_send_ini(const char *);