From e44294ea66c8bdeeb86fb1123973498200378993 Mon Sep 17 00:00:00 2001 From: gardners Date: Mon, 21 May 2012 20:45:07 +0930 Subject: [PATCH] implemented server_probe(int *pid) that used monitor interface to probe server status. Also returns PID if running (Linux only). --- commandline.c | 17 +++++++++--- monitor.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ serval.h | 6 +++++ 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/commandline.c b/commandline.c index 0af92b16..f4bc5268 100644 --- a/commandline.c +++ b/commandline.c @@ -799,14 +799,23 @@ int app_server_status(int argc, const char *const *argv, struct command_line_opt { if (cli_arg(argc, argv, o, "instance path", &thisinstancepath, cli_absolute_path, NULL) == -1) return -1; - int pid = server_pid(); - if (pid < 0) - return -1; + int pid=-1; + int status=server_probe(&pid); + cli_puts("instancepath"); cli_delim(":"); cli_puts(serval_instancepath()); cli_delim("\n"); - if (pid) { + cli_puts("status"); + cli_delim(":"); + switch(status) { + case SERVER_NOTRESPONDING: cli_puts("not responding"); break; + case SERVER_NOTRUNNING: cli_puts("stopped"); break; + case SERVER_RUNNING: cli_puts("running"); break; + case SERVER_UNKNOWN: default: cli_puts("unknown"); break; + } + cli_delim("\n"); + if (pid>-1) { cli_puts("pid"); cli_delim(":"); cli_printf("%d", pid); diff --git a/monitor.c b/monitor.c index 346c8302..7589c767 100644 --- a/monitor.c +++ b/monitor.c @@ -693,3 +693,74 @@ int monitor_tell_clients(unsigned char *msg,int msglen,int mask) } return 0; } + +/* Check if there is a running server, and whether it is responding or not. + */ +int server_probe(int *pid) +{ + int fd=-1; + struct sockaddr_un addr; + if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + return SERVER_UNKNOWN; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + addr.sun_path[0]=0; + snprintf(&addr.sun_path[1],100,"org.servalproject.servald.monitor.socket"); + int len = 1+strlen(&addr.sun_path[1]) + sizeof(addr.sun_family); + char *p=(char *)&addr; + printf("last char='%c' %02x\n",p[len-1],p[len-1]); + + if (connect(fd, (struct sockaddr*)&addr, len) == -1) { + close(fd); + return SERVER_NOTRUNNING; + } + + /* Give the server 2 seconds to send us something */ + struct pollfd fds[1]; + fds[0].fd=fd; + fds[0].events=POLLIN; + poll(fds,1,2000); + + fcntl(fd,F_SETFL,fcntl(fd, F_GETFL, NULL)|O_NONBLOCK); + + *pid=-1; + if (pid!=NULL) { +#if defined(HAVE_LINUX_STRUCT_UCRED) + struct ucred ucred; +#elif defined(HAVE_BSD_STRUCT_UCRED) + struct xucred ucred; +#else +#error "Unknown ucred struct" +#endif + socklen_t len=sizeof(ucred); + int res=getsockopt(fd,SOL_SOCKET,SO_PEERCRED,&ucred,&len); + if (len>sizeof(ucred)) { + WHYF("This is likely to be bad (memory overrun by getsockopt())"); + } + if (res) { + WHY("Failed to read credentials of monitor.socket client"); + } else { +#if defined(HAVE_LINUX_STRUCT_UCRED) + *pid = ucred.pid; +#elif defined(HAVE_BSD_STRUCT_UCRED) +#warning cannot get PID from ucred on BSD + *pid = -1; +#endif + } + } + + char buff[1024]; + int bytes=read(fd,buff,1024); + close(fd); + if (bytes<0) { + return SERVER_NOTRESPONDING; + } else if (bytes==0) { + // Could just be really busy. + return SERVER_NOTRESPONDING; + } else { + return SERVER_RUNNING; + } + +} diff --git a/serval.h b/serval.h index bc143132..d3b84649 100755 --- a/serval.h +++ b/serval.h @@ -1497,3 +1497,9 @@ int bufferAudioForPlayback(int codec,long long start_time,long long end_time, unsigned char *data,int dataLen); int startAudio(); int stopAudio(); + +#define SERVER_UNKNOWN 1 +#define SERVER_NOTRESPONDING 2 +#define SERVER_NOTRUNNING 3 +#define SERVER_RUNNING 4 +int server_probe(int *pid);