Allow closing a monitor connection to force the server to quit

This commit is contained in:
Jeremy Lakeman 2014-06-11 13:43:56 +09:30
parent 77dc7fc14c
commit 52da7778cd
7 changed files with 62 additions and 10 deletions

View File

@ -102,6 +102,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define MONITOR_PEERS (1<<2)
#define MONITOR_DNAHELPER (1<<3)
#define MONITOR_LINKS (1<<4)
#define MONITOR_QUIT (1<<5)
#define MAX_SIGNATURES 16

View File

@ -64,6 +64,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "monitor-client.h"
#include "socket.h"
#include "dataformats.h"
#include "server.h"
#ifdef HAVE_UCRED_H
#include <ucred.h>
@ -166,6 +167,10 @@ void monitor_poll(struct sched_ent *alarm)
static void monitor_close(struct monitor_context *c){
INFOF("Tearing down monitor client fd=%d", c->alarm.poll.fd);
if (serverMode && c->flags & MONITOR_QUIT){
INFOF("Quitting due to client disconnecting");
serverMode=SERVER_CLOSING;
}
unwatch(&c->alarm);
close(c->alarm.poll.fd);
c->alarm.poll.fd=-1;
@ -402,16 +407,18 @@ static int monitor_set(const struct cli_parsed *parsed, struct cli_context *cont
if (codec>=0 && codec <=255)
set_codec_flag(codec, c->supported_codecs);
}
}else if (strcase_startswith(parsed->args[1],"rhizome", NULL))
}else if (strcase_startswith(parsed->args[1],"rhizome", NULL)){
c->flags|=MONITOR_RHIZOME;
else if (strcase_startswith(parsed->args[1],"peers", NULL)){
}else if (strcase_startswith(parsed->args[1],"peers", NULL)){
c->flags|=MONITOR_PEERS;
enum_subscribers(NULL, monitor_announce_all_peers, NULL);
}else if (strcase_startswith(parsed->args[1],"dnahelper", NULL))
}else if (strcase_startswith(parsed->args[1],"dnahelper", NULL)){
c->flags|=MONITOR_DNAHELPER;
else if (strcase_startswith(parsed->args[1],"links", NULL)){
}else if (strcase_startswith(parsed->args[1],"links", NULL)){
c->flags|=MONITOR_LINKS;
link_state_announce_links();
}else if (strcase_startswith(parsed->args[1],"quit", NULL)){
c->flags|=MONITOR_QUIT;
}else
return monitor_write_error(c,"Unknown monitor type");
@ -435,6 +442,8 @@ static int monitor_clear(const struct cli_parsed *parsed, struct cli_context *co
c->flags&=~MONITOR_DNAHELPER;
else if (strcase_startswith(parsed->args[1],"links", NULL))
c->flags&=~MONITOR_LINKS;
else if (strcase_startswith(parsed->args[1],"quit", NULL))
c->flags&=~MONITOR_QUIT;
else
return monitor_write_error(c,"Unknown monitor type");

View File

@ -485,6 +485,8 @@ static int monitor_announce(struct subscriber *subscriber, void *UNUSED(context)
int link_state_announce_links(){
enum_subscribers(NULL, monitor_announce, NULL);
// announce ourselves as unreachable, mainly so that monitor clients will always get one link back
monitor_announce_link(0, NULL, my_subscriber);
return 0;
}

View File

@ -95,7 +95,7 @@ const char *_server_pidfile_path(struct __sourceloc __whence)
int server()
{
IN();
serverMode = 1;
serverMode = SERVER_RUNNING;
// Warn, not merely Info, if there is no configured log file.
logLevel_NoLogFileConfigured = LOG_LEVEL_WARN;
@ -158,16 +158,18 @@ int server()
// log message used by tests to wait for the server to start
INFO("Server initialised, entering main loop");
while (serverMode == 1 && fd_poll())
/* Check for activitiy and respond to it */
while((serverMode==SERVER_RUNNING) && fd_poll())
;
serverCleanUp();
/* It is safe to unlink the pidfile here without checking whether it actually contains our own
* PID, because server_shutdown_check() will have been executed very recently (in fd_poll()), so
* if the code reaches here, the check has been done recently.
*/
server_unlink_pid();
serverMode = 0;
RETURN(0);
OUT();
}
@ -457,9 +459,9 @@ void signal_handler(int signal)
/* Trigger the server to close gracefully after any current alarm has completed.
If we get a second signal, exit now.
*/
if (serverMode==1){
if (serverMode==SERVER_RUNNING){
INFO("Attempting clean shutdown");
serverMode=2;
serverMode=SERVER_CLOSING;
return;
}
default:

View File

@ -19,6 +19,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef __SERVAL_DNA__SERVER_H
#define __SERVAL_DNA__SERVER_H
#define SERVER_RUNNING 1
#define SERVER_CLOSING 2
DECLARE_ALARM(server_shutdown_check);
DECLARE_ALARM(server_watchdog);
DECLARE_ALARM(server_config_reload);

View File

@ -150,6 +150,17 @@ test_RemovePid() {
wait_until ! kill -0 $servald_pid 2>/dev/null
}
doc_MonitorQuit="Server stops due to monitor client disconnection"
setup_MonitorQuit() {
setup
start_servald_server
}
test_MonitorQuit() {
executeOk_servald console < <(sleep 1 && echo "monitor quit" && sleep 1)
tfw_cat --stdout --stderr
wait_until ! kill -0 $servald_pid 2>/dev/null
}
doc_NoZombie="Server process does not become a zombie"
setup_NoZombie() {
setup

View File

@ -71,6 +71,8 @@ static int console_hangup(const struct cli_parsed *parsed, struct cli_context *c
static int console_audio(const struct cli_parsed *parsed, struct cli_context *context);
static int console_usage(const struct cli_parsed *parsed, struct cli_context *context);
static int console_quit(const struct cli_parsed *parsed, struct cli_context *context);
static int console_set(const struct cli_parsed *parsed, struct cli_context *context);
static int console_clear(const struct cli_parsed *parsed, struct cli_context *context);
static void monitor_read(struct sched_ent *alarm);
struct cli_schema console_commands[]={
@ -80,6 +82,8 @@ struct cli_schema console_commands[]={
{console_usage,{"help",NULL},0,"This usage message"},
{console_audio,{"say","...",NULL},0,"Send a text string to the other party"},
{console_quit,{"quit",NULL},0,"Exit process"},
{console_set,{"monitor","<flag>",NULL},0,"Set an arbitrary monitor flag"},
{console_clear,{"ignore","<flag>",NULL},0,"Clear an arbitrary monitor flag"},
{NULL, {NULL, NULL, NULL}, 0, NULL},
};
@ -315,6 +319,26 @@ static int console_quit(const struct cli_parsed *UNUSED(parsed), struct cli_cont
return 0;
}
static int console_set(const struct cli_parsed *UNUSED(parsed), struct cli_context *UNUSED(context))
{
const char *flag;
if (cli_arg(parsed, "flag", &flag, NULL, NULL) != -1){
monitor_client_writeline(monitor_alarm.poll.fd, "monitor %s\n",
flag);
}
return 0;
}
static int console_clear(const struct cli_parsed *UNUSED(parsed), struct cli_context *UNUSED(context))
{
const char *flag;
if (cli_arg(parsed, "flag", &flag, NULL, NULL) != -1){
monitor_client_writeline(monitor_alarm.poll.fd, "ignore %s\n",
flag);
}
return 0;
}
static int console_audio(const struct cli_parsed *parsed, struct cli_context *UNUSED(context))
{
if (!calls){