mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-28 07:58:08 +01:00
Turn on self-spawning: main loop should never crash but exists only to
respawn child when it does. Add crash command to test this. Add ability to set logging level from ctrl port.
This commit is contained in:
parent
6db5eed156
commit
0291ec1e75
8 changed files with 106 additions and 31 deletions
|
@ -28,7 +28,7 @@ SRC = xwrelay.cpp \
|
|||
|
||||
OBJ = $(patsubst %.cpp,%.o,$(SRC))
|
||||
LDFLAGS += -pthread -g -lmcheck
|
||||
CPPFLAGS += -g -Wall -DSVN_REV=\"$(shell svnversion -n .)\"
|
||||
CPPFLAGS += -DSPAWN_SELF -g -Wall -DSVN_REV=\"$(shell svnversion -n .)\"
|
||||
# turn on semaphore debugging
|
||||
# CPPFLAGS += -DDEBUG_LOCKS
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ RelayConfigs* RelayConfigs::instance = NULL;
|
|||
/* static */ RelayConfigs*
|
||||
RelayConfigs::GetConfigs()
|
||||
{
|
||||
assert( instance != NULL );
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
@ -107,6 +106,8 @@ RelayConfigs::parse( const char* fname )
|
|||
m_serverName = value;
|
||||
} else if ( 0 == strcmp( line, "IDFILE" ) ) {
|
||||
m_idFileName = value;
|
||||
} else if ( 0 == strcmp( line, "LOGLEVEL" ) ) {
|
||||
m_logLevel = atoi(value);
|
||||
} else {
|
||||
logf( XW_LOGERROR, "unknown key %s with value %s\n",
|
||||
line, value );
|
||||
|
|
|
@ -39,6 +39,8 @@ class RelayConfigs {
|
|||
time_t GetHeartbeatInterval() { return m_heartbeatInterval; }
|
||||
const char* GetServerName() { return m_serverName.c_str(); }
|
||||
const char* GetIdFileName() { return m_idFileName.c_str(); }
|
||||
int GetLogLevel(void) { return m_logLevel; }
|
||||
void SetLogLevel(int ll) { m_logLevel = ll; }
|
||||
|
||||
private:
|
||||
RelayConfigs( const char* cfile );
|
||||
|
@ -48,6 +50,7 @@ class RelayConfigs {
|
|||
time_t m_heartbeatInterval;
|
||||
int m_ctrlport;
|
||||
int m_port;
|
||||
int m_logLevel;
|
||||
int m_nWorkerThreads;
|
||||
std::string m_serverName;
|
||||
std::string m_idFileName;
|
||||
|
|
|
@ -43,10 +43,12 @@
|
|||
#include "crefmgr.h"
|
||||
#include "mlock.h"
|
||||
#include "xwrelay_priv.h"
|
||||
#include "configs.h"
|
||||
|
||||
/* this is *only* for testing. Don't abuse!!!! */
|
||||
extern pthread_rwlock_t gCookieMapRWLock;
|
||||
|
||||
/* Return of true means exit the ctrl thread */
|
||||
typedef bool (*CmdPtr)( int socket, const char** args );
|
||||
|
||||
typedef struct FuncRec {
|
||||
|
@ -70,6 +72,7 @@ static bool cmd_set( int socket, const char** args );
|
|||
static bool cmd_shutdown( int socket, const char** args );
|
||||
static bool cmd_rev( int socket, const char** args );
|
||||
static bool cmd_uptime( int socket, const char** args );
|
||||
static bool cmd_crash( int socket, const char** args );
|
||||
|
||||
static void
|
||||
print_to_sock( int sock, bool addCR, const char* what, ... )
|
||||
|
@ -102,6 +105,7 @@ static const FuncRec gFuncs[] = {
|
|||
{ "set", cmd_set },
|
||||
{ "rev", cmd_rev },
|
||||
{ "uptime", cmd_uptime },
|
||||
{ "crash", cmd_crash },
|
||||
};
|
||||
|
||||
static bool
|
||||
|
@ -110,9 +114,11 @@ cmd_quit( int socket, const char** args )
|
|||
if ( 0 == strcmp( "help", args[1] ) ) {
|
||||
print_to_sock( socket, true, "* %s (disconnect from ctrl port)",
|
||||
args[0] );
|
||||
return false;
|
||||
} else {
|
||||
print_to_sock( socket, true, "bye bye" );
|
||||
return true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -136,14 +142,14 @@ static bool
|
|||
cmd_start( int socket, const char** args )
|
||||
{
|
||||
print_to_sock( socket, true, "* %s (unimplemented)", args[0] );
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
cmd_stop( int socket, const char** args )
|
||||
{
|
||||
print_to_sock( socket, true, "* %s (unimplemented)", args[0] );
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -185,24 +191,50 @@ cmd_kill_eject( int socket, const char** args )
|
|||
;
|
||||
print_to_sock( socket, true, msg, args[0], expl, args[0], args[0] );
|
||||
}
|
||||
return 1;
|
||||
return false;
|
||||
} /* cmd_kill_eject */
|
||||
|
||||
static bool
|
||||
cmd_get( int socket, const char** args )
|
||||
{
|
||||
print_to_sock( socket, true,
|
||||
"* %s -- lists all attributes (unimplemented)\n"
|
||||
"* %s <attribute> (unimplemented)",
|
||||
args[0], args[0] );
|
||||
return 1;
|
||||
if ( 0 == strcmp( args[1], "help" ) ) {
|
||||
print_to_sock( socket, true,
|
||||
"* %s -- lists all attributes (unimplemented)\n"
|
||||
"* %s loglevel",
|
||||
args[0], args[0] );
|
||||
} else {
|
||||
const char* attr = args[1];
|
||||
if ( (NULL != attr) && (0 == strcmp( attr, "loglevel" )) ) {
|
||||
RelayConfigs* rc = RelayConfigs::GetConfigs();
|
||||
if ( NULL != rc ) {
|
||||
print_to_sock( socket, true, "loglevel=%d\n",
|
||||
rc->GetLogLevel() );
|
||||
} else {
|
||||
logf( XW_LOGERROR, "RelayConfigs::GetConfigs() => NULL" );
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
cmd_set( int socket, const char** args )
|
||||
{
|
||||
print_to_sock( socket, true, "* %s <attribute> (unimplemented)", args[0] );
|
||||
return 1;
|
||||
if ( 0 == strcmp( args[1], "help" ) ) {
|
||||
print_to_sock( socket, true, "* %s loglevel <n>\n", args[0] );
|
||||
} else {
|
||||
const char* attr = args[1];
|
||||
const char* val = args[2];
|
||||
if ( (NULL != attr)
|
||||
&& (0 == strcmp( attr, "loglevel" ))
|
||||
&& (NULL != val) ) {
|
||||
RelayConfigs* rc = RelayConfigs::GetConfigs();
|
||||
if ( rc != NULL ) {
|
||||
rc->SetLogLevel( atoi(val) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -215,7 +247,7 @@ cmd_rev( int socket, const char** args )
|
|||
} else {
|
||||
print_to_sock( socket, true, "svn rev: %s", SVN_REV );
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -241,7 +273,23 @@ cmd_uptime( int socket, const char** args )
|
|||
"uptime: %d days, %d hours, %d minutes, %ld seconds",
|
||||
days, hours, minutes, seconds );
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
cmd_crash( int socket, const char** args )
|
||||
{
|
||||
if ( 0 == strcmp( args[1], "help" ) ) {
|
||||
print_to_sock( socket, true,
|
||||
"* %s -- fires an assert (debug case) or divides-by-zero",
|
||||
args[0] );
|
||||
} else {
|
||||
assert(0);
|
||||
int i = 1;
|
||||
while ( i > 0 ) --i;
|
||||
return 6/i > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -250,7 +298,7 @@ cmd_shutdown( int socket, const char** args )
|
|||
print_to_sock( socket, true,
|
||||
"* %s -- shuts down relay (exiting main) (unimplemented)",
|
||||
args[0] );
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -81,6 +81,10 @@ StateTable g_stateTable[] = {
|
|||
{ XWS_CONNECTING, XWE_DISCONNMSG, XWA_DISCONNECT, XWS_CONNECTING },
|
||||
{ XWS_MISSING, XWE_DISCONNMSG, XWA_DISCONNECT, XWS_MISSING },
|
||||
|
||||
/* I'm seeing this but not sure how to handle. Might disconnect be
|
||||
needed now */
|
||||
{ XWS_MISSING, XWE_FORWARDMSG, XWA_DISCONNECT, XWS_MISSING },
|
||||
|
||||
{ XWS_ANY, XWE_NOMORESOCKETS, XWA_NONE, XWS_DEAD },
|
||||
{ XWS_ANY, XWE_SHUTDOWN, XWA_SHUTDOWN, XWS_DEAD },
|
||||
|
||||
|
@ -115,33 +119,36 @@ StateTable g_stateTable[] = {
|
|||
/* This is our bread-n-butter */
|
||||
{ XWS_ALLCONNECTED, XWE_FORWARDMSG, XWA_FWD, XWS_ALLCONNECTED },
|
||||
|
||||
{ XWS_DEAD, XWE_REMOVESOCKET, XWA_REMOVESOCKET, XWS_DEAD },
|
||||
{ XWS_DEAD, XWE_REMOVESOCKET, XWA_REMOVESOCKET, XWS_DEAD }
|
||||
|
||||
/* Marks end of table */
|
||||
{ XWS_NONE, XWE_NONE, XWA_NONE, XWS_NONE }
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
bool
|
||||
getFromTable( XW_RELAY_STATE curState, XW_RELAY_EVENT curEvent,
|
||||
XW_RELAY_ACTION* takeAction, XW_RELAY_STATE* nextState )
|
||||
{
|
||||
bool found = false;
|
||||
StateTable* stp = g_stateTable;
|
||||
while ( stp->stateStart != XWS_NONE ) {
|
||||
const StateTable* end = stp + sizeof(g_stateTable)/sizeof(g_stateTable[0]);
|
||||
while ( stp < end ) {
|
||||
if ( stp->stateStart == curState || stp->stateStart == XWS_ANY ) {
|
||||
if ( stp->stateEvent == curEvent || stp->stateEvent == XWE_ANY ) {
|
||||
*takeAction = stp->stateAction;
|
||||
*nextState = stp->stateEnd;
|
||||
return 1;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
++stp;
|
||||
}
|
||||
|
||||
logf( XW_LOGERROR, "==> ERROR :: unable to find transition from %s on event %s",
|
||||
stateString(curState), eventString(curEvent) );
|
||||
|
||||
return 0;
|
||||
if ( !found ) {
|
||||
logf( XW_LOGERROR, "==> ERROR :: unable to find transition from %s "
|
||||
"on event %s",
|
||||
stateString(curState), eventString(curEvent) );
|
||||
}
|
||||
return found;
|
||||
} /* getFromTable */
|
||||
|
||||
#define CASESTR(s) case s: return #s
|
||||
|
|
|
@ -149,8 +149,8 @@ typedef enum {
|
|||
|
||||
} XW_RELAY_ACTION;
|
||||
|
||||
int getFromTable( XW_RELAY_STATE curState, XW_RELAY_EVENT curEvent,
|
||||
XW_RELAY_ACTION* takeAction, XW_RELAY_STATE* nextState );
|
||||
bool getFromTable( XW_RELAY_STATE curState, XW_RELAY_EVENT curEvent,
|
||||
XW_RELAY_ACTION* takeAction, XW_RELAY_STATE* nextState );
|
||||
|
||||
|
||||
char* stateString( XW_RELAY_STATE state );
|
||||
|
|
|
@ -26,4 +26,8 @@ SERVERNAME=eehouse.org
|
|||
|
||||
# Where will the file live that stores the last ID used for a new
|
||||
# connName.
|
||||
#IDFILE=/home/ehouse/xwrelay_id.txt
|
||||
IDFILE=/home/eehouse/xwrelay_id.txt
|
||||
|
||||
# Initial level of logging. See xwrelay_priv.h for values. Currently
|
||||
# 0 means errors only, 1 info, 2 verbose and 3 very verbose.
|
||||
LOGLEVEL=0
|
||||
|
|
|
@ -73,7 +73,8 @@
|
|||
void
|
||||
logf( XW_LogLevel level, const char* format, ... )
|
||||
{
|
||||
if ( level <= XW_LOGINFO ) {
|
||||
RelayConfigs* rc = RelayConfigs::GetConfigs();
|
||||
if ( NULL == rc || level <= rc->GetLogLevel() ) {
|
||||
FILE* where = stderr;
|
||||
struct tm* timp;
|
||||
struct timeval tv;
|
||||
|
@ -376,6 +377,16 @@ static int
|
|||
make_socket( unsigned long addr, unsigned short port )
|
||||
{
|
||||
int sock = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
assert( sock );
|
||||
|
||||
/* We may be relaunching after crashing with sockets open. SO_REUSEADDR
|
||||
allows them to be immediately rebound. */
|
||||
int t = true;
|
||||
if ( 0 != setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(t) ) ) {
|
||||
logf( XW_LOGERROR, "setsockopt failed. errno = %s (%d)\n",
|
||||
strerror(errno), errno );
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in sockAddr;
|
||||
sockAddr.sin_family = AF_INET;
|
||||
|
@ -543,6 +554,8 @@ int main( int argc, char** argv )
|
|||
PermID::SetServerName( serverName );
|
||||
PermID::SetIDFileName( idFileName );
|
||||
|
||||
/* add signal handling here */
|
||||
|
||||
#ifdef SPAWN_SELF
|
||||
/* loop forever, relaunching children as they die. */
|
||||
for ( ; ; ) {
|
||||
|
@ -554,7 +567,6 @@ int main( int argc, char** argv )
|
|||
logf( XW_LOGINFO, "parent waiting on child pid=%d", pid );
|
||||
waitpid( pid, &status, 0 );
|
||||
printWhy( status );
|
||||
sleep( 45 ); /* give time to close sockets? */
|
||||
} else {
|
||||
logf( XW_LOGERROR, "fork() => %s", strerror(errno) );
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue