[ROSEV_IRCSYSTEM]

- Add the forgotten "pidfile" option to the main configuration file (only required if we're running under a Posix environment)
- Don't fail on Win32 if this option is specified anyway
- Only delete the pidfile if we have created it ourselves
- Report a proper service error code if an exception occurs when running as an NT service
- Return a proper value if an exception occurs when running as a Posix daemon

svn path=/trunk/rosev_ircsystem/; revision=1237
This commit is contained in:
Colin Finck 2010-12-11 10:03:17 +00:00
parent f199b7e54a
commit 5bb183d4e9
7 changed files with 57 additions and 38 deletions

View File

@ -3,6 +3,10 @@
# set it to whatever value.
name=usually.your-hostname.com
# A file to hold the PID of the currently running server instance
# Only needed if we are running under a Posix environment
pidfile=/var/run/rosev_ircsystem.pid
# The port this server shall listen on. We only support one port,
# which either supplies unencrypted or SSL-secured access to the server.
port=6667

View File

@ -86,7 +86,10 @@ CConfiguration::ReadConfigFiles()
/* Main config file */
boost::program_options::options_description MainConfigOptions;
MainConfigOptions.add_options()
#ifndef WIN32
#ifdef WIN32
/* Don't fail if the pidfile option is specified anyway (even if it's irrelevant for the Win32 version) */
("general.pidfile", boost::program_options::value<std::string>())
#else
("general.pidfile", boost::program_options::value<std::string>(&m_PidFile)->default_value(""))
#endif
("general.name", boost::program_options::value<std::string>(&m_Name)->default_value(""))

View File

@ -9,6 +9,9 @@
#include <precomp.h>
#include <version.h>
#ifndef WIN32
static bool DeletePidFile = false;
#endif
static CConfiguration Configuration;
static boost::asio::io_service IOService;
static CIRCServer IRCServer(IOService, Configuration);
@ -16,20 +19,21 @@ static CNickServ NickServ(IRCServer);
static CLogBot LogBot(IRCServer);
static CVoteBotManager VoteBotManager(IRCServer);
static void
static int
_PrintVersion()
{
std::cout << PRODUCT_NAME "\n";
std::cout << VERSION_COPYRIGHT "\n\n";
std::cout << "This is " VERSION_ID " built on " VERSION_DATE "\n";
return 0;
}
static void
_PrintUsage()
{
std::cout << PRODUCT_NAME "\n";
std::cout << "Usage: rosev_ircsystem [options] <configuration directory>\n";
std::cout << "\n";
std::cout << "Usage: rosev_ircsystem [options] <configuration directory>\n\n";
std::cout << Configuration.GetCommandLineOptions();
}
@ -70,7 +74,8 @@ InitializeServer()
if(!PidStream)
BOOST_THROW_EXCEPTION(Error("Could not create the pidfile!") << boost::errinfo_file_name(PidFile));
PidStream << getpid();
DeletePidFile = true;
PidStream << getpid() << "\n";
PidStream.close();
#endif
@ -96,22 +101,20 @@ main(int argc, char* argv[])
if(Configuration.ParseParameters(argc, argv))
{
if(Configuration.DoPrintVersion())
_PrintVersion();
ReturnValue = _PrintVersion();
#ifdef WIN32
else if(Configuration.DoInstallService())
InstallNTService(Configuration);
ReturnValue = InstallNTService(Configuration);
else if(Configuration.DoUninstallService())
UninstallNTService();
ReturnValue = UninstallNTService();
else if(Configuration.DoRunAsDaemonService())
RunAsNTService();
ReturnValue = RunAsNTService();
#else
else if(Configuration.DoRunAsDaemonService())
RunAsPosixDaemon();
ReturnValue = RunAsPosixDaemon();
#endif
else
RunInConsole();
ReturnValue = 0;
ReturnValue = RunInConsole();
}
else
{
@ -125,10 +128,8 @@ main(int argc, char* argv[])
}
#ifndef WIN32
/* Remove the pidfile */
const std::string& PidFile = Configuration.GetPidFile();
if(!PidFile.empty())
unlink(PidFile.c_str());
if(DeletePidFile)
unlink(Configuration.GetPidFile().c_str());
#endif
return ReturnValue;

View File

@ -99,12 +99,12 @@ extern void SetSignals();
extern void ShutdownServer(int Signal = 0);
/* run_console.cpp */
extern void RunInConsole();
extern int RunInConsole();
/* run_nt_service.cpp */
extern void InstallNTService(CConfiguration& Configuration);
extern void RunAsNTService();
extern void UninstallNTService();
extern int InstallNTService(CConfiguration& Configuration);
extern int RunAsNTService();
extern int UninstallNTService();
/* run_posix_daemon.cpp */
extern void RunAsPosixDaemon();
extern int RunAsPosixDaemon();

View File

@ -9,7 +9,7 @@
#include <precomp.h>
#include <version.h>
void
int
RunInConsole()
{
Info("*******************************************************************************\n");
@ -21,4 +21,6 @@ RunInConsole()
SetSignals();
InitializeServer();
RunServerEventLoop();
return 0;
}

View File

@ -55,13 +55,6 @@ _AddEventSource()
BOOST_THROW_EXCEPTION(Error("Failed to add the event source!") << boost::errinfo_api_function("RegSetValueExA") << Win32Error_Info(Result));
}
static void
_ReportServiceStatus(DWORD NewState)
{
ServiceStatus.dwCurrentState = NewState;
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
}
static DWORD WINAPI
_ServiceControlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
@ -74,7 +67,8 @@ _ServiceControlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData,
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
_ReportServiceStatus(SERVICE_STOP_PENDING);
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
ShutdownServer();
return NO_ERROR;
@ -91,11 +85,12 @@ _ServiceMainA(DWORD dwArgc, LPSTR* lpszArgv)
/* Report initial SERVICE_START_PENDING status */
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwWaitHint = 4000;
ServiceStatus.dwWin32ExitCode = NO_ERROR;
_ReportServiceStatus(SERVICE_START_PENDING);
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
/* Get us an event log handle for logging errors */
HANDLE EventLogHandle = RegisterEventSourceA(NULL, PRODUCT_NAME);
@ -104,7 +99,8 @@ _ServiceMainA(DWORD dwArgc, LPSTR* lpszArgv)
try
{
InitializeServer();
_ReportServiceStatus(SERVICE_RUNNING);
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
RunServerEventLoop();
}
catch(std::exception& Exception)
@ -113,14 +109,17 @@ _ServiceMainA(DWORD dwArgc, LPSTR* lpszArgv)
std::string ExceptionMessage(boost::diagnostic_information(Exception));
const char* InsertStrings[] = {ExceptionMessage.c_str()};
ReportEventA(EventLogHandle, EVENTLOG_ERROR_TYPE, 0, GENERAL_EXCEPTION, NULL, 1, NULL, InsertStrings, NULL);
ServiceStatus.dwWin32ExitCode = ERROR_EXCEPTION_IN_SERVICE;
}
/* We're done */
_ReportServiceStatus(SERVICE_STOPPED);
DeregisterEventSource(EventLogHandle);
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
}
void
int
InstallNTService(CConfiguration& Configuration)
{
/* Get the path to our executable file and append the corresponding arguments to it */
@ -177,9 +176,10 @@ InstallNTService(CConfiguration& Configuration)
_AddEventSource();
std::cout << "The service has been installed successfully!\n";
return 0;
}
void
int
RunAsNTService()
{
char ServiceName[] = APPLICATION_NAME;
@ -191,9 +191,11 @@ RunAsNTService()
if(!StartServiceCtrlDispatcherA(ServiceTable))
BOOST_THROW_EXCEPTION(Error("Failed to start the service control dispatcher!") << Win32Error_Info(GetLastError()));
return 0;
}
void
int
UninstallNTService()
{
/* Get access to the service manager */
@ -226,4 +228,6 @@ UninstallNTService()
CloseServiceHandle(ServiceHandle);
CloseServiceHandle(SCManagerHandle);
return 0;
}

View File

@ -12,7 +12,7 @@
/**
* Does most tasks described in http://www.enderunix.org/docs/eng/daemon.php before initializing the server.
*/
void
int
RunAsPosixDaemon()
{
/* Fork the process to create a background one. */
@ -34,11 +34,14 @@ RunAsPosixDaemon()
/* We're the child process and can continue now. */
SetSignals();
openlog(APPLICATION_NAME, LOG_PID, LOG_DAEMON);
int ReturnValue = 1;
try
{
InitializeServer();
RunServerEventLoop();
ReturnValue = 0;
}
catch(std::exception& Exception)
{
@ -47,4 +50,6 @@ RunAsPosixDaemon()
}
closelog();
return ReturnValue;
}