Terminate server process if serval.pid clobbered

This commit is contained in:
Andrew Bettison 2012-05-08 11:23:43 +09:30
parent 27f2d00d5e
commit acc5e48f4f
5 changed files with 72 additions and 54 deletions

View File

@ -33,36 +33,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h"
#include "rhizome.h"
/** Return the PID of the currently running server process, return 0 if there is none.
*/
static int servalNodeRunning()
{
const char *instancepath = serval_instancepath();
struct stat st;
if (stat(instancepath, &st) == -1)
return setReason(
"Instance path '%s' non existant or not accessable: %s [errno=%d]"
" (Set SERVALINSTANCE_PATH to specify an alternate location)",
instancepath, strerror(errno), errno
);
if ((st.st_mode & S_IFMT) != S_IFDIR)
return setReason("Instance path '%s' is not a directory", instancepath);
char filename[1024];
if (!FORM_SERVAL_INSTANCE_PATH(filename, "serval.pid"))
return -1;
FILE *f = NULL;
if ((f = fopen(filename, "r"))) {
char buf[20];
fgets(buf, sizeof buf, f);
fclose(f);
int pid = atoi(buf);
if (pid > 0 && kill(pid, 0) != -1)
return pid;
unlink(filename);
}
return 0;
}
int cli_usage() {
fprintf(stderr,"\nServal Mesh version <version>.\n");
fprintf(stderr,"Usage:\n");
@ -589,7 +559,7 @@ int app_server_start(int argc, const char *const *argv, struct command_line_opti
if (!interfaces[0])
WHY("No network interfaces configured (empty 'interfaces' config setting)");
overlay_interface_args(interfaces);
int pid = servalNodeRunning();
int pid = server_pid();
if (pid < 0)
return -1;
int ret = 1;
@ -631,7 +601,7 @@ int app_server_start(int argc, const char *const *argv, struct command_line_opti
happening. */
time_t timeout = time(NULL) + 5;
int rpid;
while (time(NULL) < timeout && (rpid = servalNodeRunning()) == 0)
while (time(NULL) < timeout && (rpid = server_pid()) == 0)
usleep(200000); // 5 Hz
if (rpid == -1)
return -1;
@ -662,7 +632,7 @@ int app_server_stop(int argc, const char *const *argv, struct command_line_optio
if (cli_arg(argc, argv, o, "instance path", &thisinstancepath, cli_absolute_path, NULL) == -1)
return -1;
const char *instancepath = serval_instancepath();
int pid = servalNodeRunning();
int pid = server_pid();
if (pid < 0)
return -1;
cli_puts("instancepath");
@ -705,7 +675,7 @@ int app_server_stop(int argc, const char *const *argv, struct command_line_optio
/* Allow a few seconds for the process to die, and keep an eye on things while this is
happening. */
time_t timeout = time(NULL) + 2;
while (time(NULL) < timeout && servalNodeRunning() == pid)
while (time(NULL) < timeout && server_pid() == pid)
usleep(200000); // 5 Hz
}
cli_puts("tries");
@ -720,7 +690,7 @@ 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 = servalNodeRunning();
int pid = server_pid();
if (pid < 0)
return -1;
cli_puts("instancepath");

18
dna.c
View File

@ -317,18 +317,12 @@ void signal_handler( int signal ) {
exit(0);
case SIGHUP:
case SIGINT:
/* Shut down.
The shutting down should be done from the main-line code rather than here,
so we first try to tell the mainline code to do so. If, however, this is
not the first time we have been asked to shut down, then we will do it here. */
if (servalShutdown) {
/* We have been asked before, so shut down cleanly */
serverCleanUp();
exit(0);
} else {
WHY("Asking Serval process to shutdown cleanly");
servalShutdown=1;
}
/* Terminate the server process. The shutting down should be done from the main-line code
rather than here, so we first try to tell the mainline code to do so. If, however, this is
not the first time we have been asked to shut down, then we will do it here. */
server_shutdown_check();
WHY("Asking Serval process to shutdown cleanly");
servalShutdown = 1;
return;
}

View File

@ -78,6 +78,8 @@ keyring_file *keyring=NULL;
int overlayServerMode()
{
long long server_pid_time_ms = overlay_gettime_ms();
/* In overlay mode we need to listen to all of our sockets, and also to
send periodic traffic. This means we need to */
fprintf(stderr,"Running in overlay mode.\n");
@ -118,13 +120,10 @@ int overlayServerMode()
/* Get rhizome server started BEFORE populating fd list so that
the server's listen socket is in the list for poll() */
if (rhizome_datastore_path) rhizome_server_poll();
while(1) {
if (servalShutdown) {
serverCleanUp();
exit(0);
}
server_shutdown_check();
/* Work out how long we can wait before we need to tick */
long long ms=overlay_time_until_next_tick();

View File

@ -397,7 +397,9 @@ int respondSimple(keyring_identity *id,
int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffer,int buffer_length,int *len,
unsigned char *transaction_id);
int requestNewHLR(char *did,char *pin,char *sid,int recvttl,struct sockaddr *recvaddr);
int server_pid();
int server(char *backing_file);
void server_shutdown_check();
int isTransactionInCache(unsigned char *transaction_id);
void insertTransactionInCache(unsigned char *transaction_id);

View File

@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h"
static int server_getpid = 0;
unsigned char *hlr=NULL;
int hlr_size=0;
@ -97,6 +98,35 @@ int recvwithttl(int sock,unsigned char *buffer,int bufferlen,int *ttl,
return len;
}
/** Return the PID of the currently running server process, return 0 if there is none.
*/
int server_pid()
{
const char *instancepath = serval_instancepath();
struct stat st;
if (stat(instancepath, &st) == -1)
return setReason(
"Instance path '%s' non existant or not accessable: %s [errno=%d]"
" (Set SERVALINSTANCE_PATH to specify an alternate location)",
instancepath, strerror(errno), errno
);
if ((st.st_mode & S_IFMT) != S_IFDIR)
return setReason("Instance path '%s' is not a directory", instancepath);
char filename[1024];
if (!FORM_SERVAL_INSTANCE_PATH(filename, "serval.pid"))
return -1;
FILE *f = NULL;
if ((f = fopen(filename, "r"))) {
char buf[20];
fgets(buf, sizeof buf, f);
fclose(f);
int pid = atoi(buf);
if (pid > 0 && kill(pid, 0) != -1)
return pid;
unlink(filename);
}
return 0;
}
int server(char *backing_file)
{
@ -122,7 +152,7 @@ int server(char *backing_file)
getKeyring(backing_file);
}
/* Record PID */
/* Record PID to advertise that the server is now running */
char filename[1024];
if (!FORM_SERVAL_INSTANCE_PATH(filename, "serval.pid"))
return -1;
@ -132,7 +162,8 @@ int server(char *backing_file)
perror("fopen");
return -1;
}
fprintf(f,"%d\n",getpid());
server_getpid = getpid();
fprintf(f,"%d\n", server_getpid);
fclose(f);
if (!overlayMode) simpleServerMode();
@ -141,6 +172,28 @@ int server(char *backing_file)
return 0;
}
/* Called periodically by the server process in its main loop.
*/
void server_shutdown_check()
{
static long long server_pid_time_ms = 0;
if (servalShutdown) {
serverCleanUp();
exit(0);
}
/* If this server has been supplanted with another or Serval has been uninstalled, then its PID
file will change or be unaccessible. In this case, shut down without all the cleanup.
Perform this check at most once per second. */
long long time_ms = overlay_gettime_ms();
if (server_pid_time_ms == 0 || time_ms - server_pid_time_ms > 1000) {
server_pid_time_ms = time_ms;
if (server_pid() != server_getpid) {
WHYF("Server pid file no longer contains my pid=%d -- shutting down without cleanup", server_pid);
exit(1);
}
}
}
int getKeyring(char *backing_file)
{
if (!backing_file)