Fix bodgy server start/stop logic

Rename pidfile 'serval.pid' to 'servald.pid'
Rename stopfile 'doshutdown' to 'servald.stop'
Reinstate checking of stopfile on signals and in main loops
Correct delay loops in 'start' and 'stop' commands
Move some code from commandline.c to server.c
This commit is contained in:
Andrew Bettison 2012-05-08 12:19:52 +09:30
parent 6376baf8b8
commit 329189ec8c
4 changed files with 83 additions and 44 deletions

View File

@ -596,12 +596,15 @@ int app_server_start(int argc, const char *const *argv, struct command_line_opti
return server(NULL);
}
default: { // Parent process
/* Allow a few seconds for the process to start, and keep an eye on things while this is
happening. */
time_t timeout = time(NULL) + 5;
int rpid;
while (time(NULL) < timeout && (rpid = server_pid()) == 0)
usleep(200000); // 5 Hz
/* Allow a few seconds for the process to start. */
int rpid = 0;
time_t timeout = overlay_gettime_ms() + 5000;
do {
struct timespec delay;
delay.tv_sec = 0;
delay.tv_nsec = 200000000; // 200 ms = 5 Hz
nanosleep(&delay, NULL);
} while ((rpid = server_pid()) == 0 && overlay_gettime_ms() < timeout);
if (rpid == -1)
return -1;
if (rpid == 0)
@ -644,7 +647,8 @@ int app_server_stop(int argc, const char *const *argv, struct command_line_optio
cli_printf("%d", pid);
cli_delim("\n");
int tries = 0;
while (1) {
int running = pid;
while (running == pid) {
if (tries >= 5)
return WHYF(
"Serval process for instance '%s' did not stop after %d SIGHUP signals",
@ -653,16 +657,10 @@ int app_server_stop(int argc, const char *const *argv, struct command_line_optio
++tries;
/* Create the stopfile, which causes the server process's signal handler to exit
instead of restarting. */
char stopfile[1024];
if (!FORM_SERVAL_INSTANCE_PATH(stopfile, "doshutdown"))
return -1;
FILE *f;
if ((f = fopen(stopfile, "w")) == NULL)
return WHYF("Could not create shutdown file '%s'", stopfile);
fclose(f);
if (kill(pid,SIGHUP) == -1) {
server_create_stopfile();
if (kill(pid, SIGHUP) == -1) {
// ESRCH means process is gone, possibly we are racing with another stop, or servald just
// died unexpectedly.
// died voluntarily.
if (errno == ESRCH) {
serverCleanUp();
break;
@ -671,11 +669,14 @@ int app_server_stop(int argc, const char *const *argv, struct command_line_optio
instancepath, pid, strerror(errno), errno
);
}
/* 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 && server_pid() == pid)
usleep(200000); // 5 Hz
/* Allow a few seconds for the process to die. */
time_t timeout = overlay_gettime_ms() + 2000;
do {
struct timespec delay;
delay.tv_sec = 0;
delay.tv_nsec = 200000000; // 200 ms = 5 Hz
nanosleep(&delay, NULL);
} while ((running = server_pid()) == pid && overlay_gettime_ms() < timeout);
}
cli_puts("tries");
cli_delim(":");

19
dna.c
View File

@ -290,25 +290,6 @@ int create_serval_instance_dir() {
return 0;
}
void serverCleanUp()
{
/* Try to remove shutdown and PID files and exit */
char filename[1024];
if (FORM_SERVAL_INSTANCE_PATH(filename, "doshutdown")) {
unlink(filename);
}
if (FORM_SERVAL_INSTANCE_PATH(filename, "serval.pid")) {
unlink(filename);
}
if (mdp_client_socket==-1) {
if (FORM_SERVAL_INSTANCE_PATH(filename, "mdp.socket")) {
unlink(filename);
}
} else {
overlay_mdp_client_done();
}
}
void signal_handler( int signal ) {
switch (signal) {

View File

@ -381,7 +381,6 @@ extern int hexdigit[16];
extern int sock;
void serverCleanUp();
char *confValueGet(char *var,char *defaultValue);
int recvwithttl(int sock,unsigned char *buffer,int bufferlen,int *ttl,
struct sockaddr *recvaddr,unsigned int *recvaddrlen);
@ -400,6 +399,9 @@ int requestNewHLR(char *did,char *pin,char *sid,int recvttl,struct sockaddr *rec
int server_pid();
int server(char *backing_file);
void server_shutdown_check();
int server_create_stopfile();
int server_check_stopfile();
void serverCleanUp();
int isTransactionInCache(unsigned char *transaction_id);
void insertTransactionInCache(unsigned char *transaction_id);

View File

@ -18,12 +18,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include "serval.h"
#define PIDFILE_NAME "servald.pid"
#define STOPFILE_NAME "servald.stop"
static int server_getpid = 0;
unsigned char *hlr=NULL;
int hlr_size=0;
@ -114,7 +118,7 @@ int server_pid()
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"))
if (!FORM_SERVAL_INSTANCE_PATH(filename, PIDFILE_NAME))
return -1;
FILE *f = NULL;
if ((f = fopen(filename, "r"))) {
@ -155,7 +159,7 @@ int server(char *backing_file)
/* Record PID to advertise that the server is now running */
char filename[1024];
if (!FORM_SERVAL_INSTANCE_PATH(filename, "serval.pid"))
if (!FORM_SERVAL_INSTANCE_PATH(filename, PIDFILE_NAME))
return -1;
FILE *f=fopen(filename,"w");
if (!f) {
@ -177,14 +181,20 @@ int server(char *backing_file)
*/
void server_shutdown_check()
{
static long long server_pid_time_ms = 0;
if (servalShutdown) {
WHY("Shutdown flag set -- terminating with cleanup");
serverCleanUp();
exit(0);
}
if (server_check_stopfile() == 1) {
WHY("Shutdown file exists -- terminating with cleanup");
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. */
static long long server_pid_time_ms = 0;
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;
@ -195,6 +205,51 @@ void server_shutdown_check()
}
}
int server_create_stopfile()
{
char stopfile[1024];
if (!FORM_SERVAL_INSTANCE_PATH(stopfile, STOPFILE_NAME))
return -1;
FILE *f;
if ((f = fopen(stopfile, "w")) == NULL)
return WHYF("Could not create stopfile '%s'", stopfile);
fclose(f);
return 0;
}
int server_check_stopfile()
{
char stopfile[1024];
if (!FORM_SERVAL_INSTANCE_PATH(stopfile, STOPFILE_NAME))
return -1;
int r = access(stopfile, F_OK);
if (r == 0)
return 1;
if (r == -1 && errno == ENOENT)
return 0;
WHYF("Access check for stopfile '%s' failed: %s [errno=%d]", stopfile, strerror(errno), errno);
return -1;
}
void serverCleanUp()
{
/* Try to remove shutdown and PID files and exit */
char filename[1024];
if (FORM_SERVAL_INSTANCE_PATH(filename, STOPFILE_NAME)) {
unlink(filename);
}
if (FORM_SERVAL_INSTANCE_PATH(filename, PIDFILE_NAME)) {
unlink(filename);
}
if (mdp_client_socket==-1) {
if (FORM_SERVAL_INSTANCE_PATH(filename, "mdp.socket")) {
unlink(filename);
}
} else {
overlay_mdp_client_done();
}
}
int getKeyring(char *backing_file)
{
if (!backing_file)