Esempio n. 1
0
int _cdecl main( int argc, char * argv[] )
#endif
{
#ifndef _WIN32
	// Initialize nonblocking IO and disable readline on linux
	g_UnixTerminal.prepare();
#endif

	g_Serv.m_iExitFlag = Sphere_InitServer( argc, argv );
	if ( ! g_Serv.m_iExitFlag )
	{
		WritePidFile();

		// Start the ping server, this can only be ran in a separate thread
		if ( IsSetEF( EF_UsePingServer ) )
			g_PingServer.start();
		
#if !defined(_WIN32) || defined(_LIBEV)
		if ( g_Cfg.m_fUseAsyncNetwork != 0 )
			g_NetworkEvent.start();
#endif

#ifndef _MTNETWORK
		g_NetworkIn.onStart();
		if (IsSetEF( EF_NetworkOutThread ))
			g_NetworkOut.start();
#else
		g_NetworkManager.start();
#endif
			
		bool shouldRunInThread = ( g_Cfg.m_iFreezeRestartTime > 0 );

		if( shouldRunInThread )
		{
			g_Main.start();
			Sphere_MainMonitorLoop();
		}
		else
		{
			while( !g_Serv.m_iExitFlag )
			{
				g_Main.tick();
			}
		}
	}

#ifdef _WIN32
	NTWindow_DeleteIcon();
#endif

	Sphere_ExitServer();
	WritePidFile(true);
	return( g_Serv.m_iExitFlag );
}
Esempio n. 2
0
int Daemon::Start(const char* pidFile)
{
    int pid = ReadPidFile(pidFile);
    if (pid > 0 && 0 == kill(pid, 0))
    {//有另一个已经存在的进程
        GLOG(IM_ERROR, "another pid is running, pid=%d", pid);
        return -1;
    }
    //fork两次
    for (int i = 0; i < 2; ++i)
    {
        switch (fork())
        {
            case -1: //error
                GLOG(IM_ERROR, "call fork() error");
                return -1;
            case 0://子进程
                break;
            default://父进程退出
                exit(0);
        }
        setsid();
    }
    //写pid文件
    if (WritePidFile(pidFile) != 0)
    {
        return -1;
    }

    int fd = open("/dev/null", O_RDWR);
    if (-1 == fd)
    {
        GLOG(IM_ERROR, "call open() failed");
        return -1;
    }
    //0重定向到/dev/null
    if (dup2(fd, 0) == -1)
    {//stdin
        GLOG(IM_ERROR, "call dup2() failed");
        return -1;
    }
    //1重定向到/dev/null
    if (dup2(fd, 1) == -1)
    {//stdout
        GLOG(IM_ERROR, "call dup2() failed");
        return -1;
    }
    //关闭fd
    if (fd > 2) 
    {
        if (close(fd) == -1) 
        {
            GLOG(IM_ERROR, "call close(%d) error", fd);
            return -1;
        }
    }
    return 0;
}
Esempio n. 3
0
void SetupPidFile()
{
char *Tempstr=NULL;


Tempstr=SessionSubstituteVars(Tempstr,Settings.PidFile,NULL);

PidFile=WritePidFile(Tempstr);
DestroyString(Tempstr);
}
Esempio n. 4
0
int Sphere_InitServer( int argc, char *argv[] )
{
#ifdef EXCEPTIONS_DEBUG
	const char *m_sClassName = "Sphere";
#endif
	EXC_TRY("Init");
	ASSERT(MAX_BUFFER >= sizeof(CEvent));
	ASSERT(sizeof(int) == sizeof(DWORD));	// make this assumption often.
	ASSERT(sizeof(ITEMID_TYPE) == sizeof(DWORD));
	ASSERT(sizeof(WORD) == 2 );
	ASSERT(sizeof(DWORD) == 4 );
	ASSERT(sizeof(NWORD) == 2 );
	ASSERT(sizeof(NDWORD) == 4 );
	ASSERT(sizeof(CUOItemTypeRec) == 37 ); // byte pack working ?
	ASSERT((std::numeric_limits<size_t>::min)() == 0); // ensure unsigned

#ifdef _WIN32
	if ( !QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&llTimeProfileFrequency)) )
		llTimeProfileFrequency = 1000;

	#if !defined(_DEBUG) && !defined(__MINGW32__)
		EXC_SET("setting exception catcher");
		SetExceptionTranslator();
	#endif
#endif

	EXC_SET("loading");
	if ( !g_Serv.Load() )
		return -3;

	if ( argc > 1 )
	{
		EXC_SET("cmdline");
		if ( !g_Serv.CommandLine(argc, argv) )
			return -1;
	}

	WritePidFile(2);

	EXC_SET("load world");
	if ( !g_World.LoadAll() )
		return -8;

	EXC_SET("sockets init");
	if ( !g_Serv.SocketsInit() )
		return -9;

	//	load auto-complete dictionary
	EXC_SET("auto-complete");
	{
		CFileText	dict;
		if ( dict.Open(SPHERE_FILE ".dic", OF_READ|OF_TEXT|OF_DEFAULTMODE) )
		{
			TCHAR * pszTemp = Str_GetTemp();
			size_t count = 0;
			while ( !dict.IsEOF() )
			{
				dict.ReadString(pszTemp, SCRIPT_MAX_LINE_LEN-1);
				if ( *pszTemp )
				{
					TCHAR *c = strchr(pszTemp, '\r');
					if ( c != NULL )
						*c = '\0';

					c = strchr(pszTemp, '\n');
					if ( c != NULL )
						*c = '\0';

					if ( *pszTemp != '\0' )
					{
						count++;
						g_AutoComplete.AddTail(pszTemp);
					}
				}
			}
			g_Log.Event(LOGM_INIT, "Auto-complete dictionary loaded (contains %" FMTSIZE_T " words)\n", count);
			dict.Close();
		}
	}

	EXC_SET("finalizing");
	g_Serv.SetServerMode(SERVMODE_Run);
	g_Log.Event(LOGM_INIT, "Startup complete (Items=%lu, Chars=%lu, Accounts=%lu)\nPress '?' for console commands\n\n", g_Serv.StatGet(SERV_STAT_ITEMS), g_Serv.StatGet(SERV_STAT_CHARS), g_Serv.StatGet(SERV_STAT_ACCOUNTS));

	if ( !g_Accounts.Account_GetCount() )
		g_Log.Event(LOGL_WARN|LOGM_INIT, "The server has no accounts. To create admin account you must type:\n  ACCOUNT ADD [login] [password]\n  ACCOUNT [login] PLEVEL 7\n");

	// Trigger server start
	g_Serv.r_Call("f_onserver_start", &g_Serv, NULL);
	return g_Serv.m_iExitFlag;

	EXC_CATCH;

	EXC_DEBUG_START;
	g_Log.EventDebug("cmdline argc=%d starting with %p (argv1='%s')\n", argc, static_cast<void *>(argv), ( argc > 2 ) ? argv[1] : "");
	EXC_DEBUG_END;
	return -10;
}
Esempio n. 5
0
int Sphere_InitServer( int argc, char *argv[] )
{
	const char *m_sClassName = "Sphere";
	EXC_TRY("Init");
	ASSERT(MAX_BUFFER >= sizeof(CCommand));
	ASSERT(MAX_BUFFER >= sizeof(CEvent));
	ASSERT(sizeof(int) == sizeof(DWORD));	// make this assumption often.
	ASSERT(sizeof(ITEMID_TYPE) == sizeof(DWORD));
	ASSERT(sizeof(WORD) == 2 );
	ASSERT(sizeof(DWORD) == 4 );
	ASSERT(sizeof(NWORD) == 2 );
	ASSERT(sizeof(NDWORD) == 4 );
	ASSERT(sizeof(CUOItemTypeRec) == 37 ); // byte pack working ?
	ASSERT((std::numeric_limits<size_t>::min)() == 0); // ensure unsigned

#ifdef _WIN32
	if ( !QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&llTimeProfileFrequency)))
		llTimeProfileFrequency = 1000;

	EXC_SET("setting exception catcher");
	SetExceptionTranslator();
#endif // _WIN32

	EXC_SET("loading");
	if ( !g_Serv.Load() )
		return -3;

	if ( argc > 1 )
	{
		EXC_SET("cmdline");
		if ( !g_Serv.CommandLine(argc, argv) )
			return -1;
	}

	WritePidFile(2);

	EXC_SET("sockets init");
	if ( !g_Serv.SocketsInit() )
		return -9;
	EXC_SET("load world");
	if ( !g_World.LoadAll() )
		return -8;

	//	load auto-complete dictionary
	EXC_SET("auto-complete");
	{
		CFileText	dict;
		if ( dict.Open(GRAY_FILE ".dic", OF_READ|OF_TEXT|OF_DEFAULTMODE) )
		{
			TCHAR * pszTemp = Str_GetTemp();
			size_t count = 0;
			while ( !dict.IsEOF() )
			{
				dict.ReadString(pszTemp, SCRIPT_MAX_LINE_LEN-1);
				if ( *pszTemp )
				{
					TCHAR *c = strchr(pszTemp, '\r');
					if ( c != NULL )
						*c = '\0';

					c = strchr(pszTemp, '\n');
					if ( c != NULL )
						*c = '\0';

					if ( *pszTemp != '\0' )
					{
						count++;
						g_AutoComplete.AddTail(pszTemp);
					}
				}
			}
			g_Log.Event(LOGM_INIT, "Auto-complete dictionary loaded (contains %" FMTSIZE_T " words).\n", count);
			dict.Close();
		}
	}
	g_Serv.SetServerMode(SERVMODE_Run);	// ready to go.

	// Display EF/OF Flags
	g_Cfg.PrintEFOFFlags();

	EXC_SET("finilizing");
	g_Log.Event(LOGM_INIT, "%s", g_Serv.GetStatusString(0x24));
	g_Log.Event(LOGM_INIT, "Startup complete. items=%lu, chars=%lu\n", g_Serv.StatGet(SERV_STAT_ITEMS), g_Serv.StatGet(SERV_STAT_CHARS));

#ifdef _WIN32
	g_Log.Event(LOGM_INIT, "Press '?' for console commands\n");
#endif

	// Trigger server start
	g_Serv.r_Call("f_onserver_start", &g_Serv, NULL);
	return 0;

	EXC_CATCH;

	EXC_DEBUG_START;
	g_Log.EventDebug("cmdline argc=%d starting with %p (argv1='%s')\n", argc, static_cast<void *>(argv), ( argc > 2 ) ? argv[1] : "");
	EXC_DEBUG_END;
	return -10;
}
Esempio n. 6
0
bool Initialize() {
	Logger::Init();

	if ((bool)gRs.commandLine["arguments"]["--use-implicit-console-appender"]) {
		Variant dummy;
		dummy[CONF_LOG_APPENDER_NAME] = "implicit console appender";
		dummy[CONF_LOG_APPENDER_TYPE] = CONF_LOG_APPENDER_TYPE_CONSOLE;
		dummy[CONF_LOG_APPENDER_COLORED] = (bool)true;
		dummy[CONF_LOG_APPENDER_LEVEL] = (uint32_t) 6;
		ConsoleLogLocation * pLogLocation = new ConsoleLogLocation(dummy);
		pLogLocation->SetLevel(_FINEST_);
		Logger::AddLogLocation(pLogLocation);
	}

	INFO("Reading configuration from %s", STR(gRs.commandLine["arguments"]["configFile"]));
#ifdef COMPILE_STATIC
	gRs.pConfigFile = new ConfigFile(SpawnApplication, SpawnFactory);
#else
	gRs.pConfigFile = new ConfigFile(NULL, NULL);
#endif
	string configFilePath = gRs.commandLine["arguments"]["configFile"];
	string fileName;
	string extension;
	splitFileName(configFilePath, fileName, extension);

	if (lowerCase(extension) == "xml") {
		if (!gRs.pConfigFile->LoadXmlFile(configFilePath,
				(bool)gRs.commandLine["arguments"]["--daemon"])) {
			FATAL("Unable to load file %s", STR(configFilePath));
			return false;
		}
	} else if (lowerCase(extension) == "lua") {
#ifdef HAS_LUA
		if (!gRs.pConfigFile->LoadLuaFile(configFilePath,
				(bool)gRs.commandLine["arguments"]["--daemon"])) {
			FATAL("Unable to load file %s", STR(configFilePath));
			return false;
		}
#else
		fprintf(stdout, "Lua is not supported by the current build of the server\n");
		ASSERT("Lua is not supported by the current build of the server");
		return false;
#endif /* HAS_LUA */
	} else {
		FATAL("Invalid file format: %s", STR(configFilePath));
		return false;
	}

#ifndef WIN32
	if (gRs.pConfigFile->IsDaemon()) {
		if (!gRs.daemon) {
			INFO("Daemonize...");
			pid_t pid = fork();
			if (pid < 0) {
				FATAL("Unable to start as daemon. fork() failed");
				return false;
			}

			if (pid > 0) {
				if (gRs.commandLine["arguments"].HasKey("--pid"))
					WritePidFile(pid);
				return false;
			}

			FINEST("Create a new SID for the daemon");
			pid_t sid = setsid();
			if (sid < 0) {
				FATAL("Unable to start as daemon. setsid() failed");
				return false;
			}

			int fd = open("/dev/null", O_RDWR, 0);
			if (fd < 0) {
				FATAL("Unable to start as daemon. open(/dev/null) failed");
				return false;
			}
			(void) dup2(fd, STDIN_FILENO);
			(void) dup2(fd, STDOUT_FILENO);
			(void) dup2(fd, STDERR_FILENO);
			if (fd > 2) {
				(void) close(fd);
			}

			gRs.daemon = true;

			Logger::SignalFork();
		}
	}
#endif /* WIN32 */

	INFO("Configure logger");
	if (!gRs.pConfigFile->ConfigLogAppenders()) {
		FATAL("Unable to configure log appenders");
		return false;
	}

	INFO("%s", STR(Version::GetBanner()));

	INFO("Initialize I/O handlers manager: %s", NETWORK_REACTOR);
	IOHandlerManager::Initialize();

	INFO("Configure modules");
	if (!gRs.pConfigFile->ConfigModules()) {
		FATAL("Unable to configure modules");
		return false;
	}

	INFO("Plug in the default protocol factory");
	gRs.pProtocolFactory = new DefaultProtocolFactory();
	if (!ProtocolFactoryManager::RegisterProtocolFactory(gRs.pProtocolFactory)) {
		FATAL("Unable to register default protocols factory");
		return false;
	}

	INFO("Configure factories");
	if (!gRs.pConfigFile->ConfigFactories()) {
		FATAL("Unable to configure factories");
		return false;
	}

	INFO("Configure acceptors");
	if (!gRs.pConfigFile->ConfigAcceptors()) {
		FATAL("Unable to configure acceptors");
		return false;
	}

	INFO("Configure instances");
	if (!gRs.pConfigFile->ConfigInstances()) {
		FATAL("Unable to configure instances");
		return false;
	}

	INFO("Start I/O handlers manager: %s", NETWORK_REACTOR);
	IOHandlerManager::Start();

	INFO("Configure applications");
	if (!gRs.pConfigFile->ConfigApplications()) {
		FATAL("Unable to configure applications");
		return false;
	}

	INFO("Install the quit signal");
	installQuitSignal(QuitSignalHandler);

	return true;
}
Esempio n. 7
0
int main(int argc, char *argv[])
{
    int servSock;                    /* Socket descriptor for server */
    unsigned short echoServPort;     /* Server port */
    pid_t processID;                 /* Process ID */
    FILE *efp;
    FILE *afp;                 /* Error and access files */
    FILE *seq_in;
    char *execname;
    char *pidpath;    
    char *logpath;
    int summarise_coords = 0, d_flag = 0, c;

    while ((c = getopt (argc, argv, "m:hdc")) != -1)
       switch (c) {
            case 'h':
                usage(argv[0]);
                exit(0);
                break;
            case 'm':
                // i5 comptability - matrix option no longer needed. added to prevent warnings
                break;
            case 'c':
                summarise_coords = 1;  // i5 output - list of start/end pairs
                break;
            case 'd':
                d_flag = 1; // daemon mode
                break;
        }

    if (! d_flag) {
        process_seq_stdin(summarise_coords); // run standalone - either printing a list of p values of the list of start/end for i5
        exit(0);
    } else { // deamonise
        if (argc - optind != 3) // Test for correct number of arguments
                                // optind is the number of real (excluding $0/-xxx) arguments, or the index into the first real argument
        {
            usage(argv[0]);
            exit(1);
        }
    }

    execname = "ncoilsd";
    pidpath = argv[optind + 1];
    logpath = argv[optind + 2];

    /* Open the logs */ 
    OpenLog(&efp, ERROR, logpath, execname);
    OpenLog(&afp, LOG, logpath, execname);
    
    echoServPort = atoi(argv[optind]);  /* First arg:  local port */
    LogMessage(afp, "Trying to listening on port %d\n", echoServPort); 
    servSock = CreateTCPServerSocket(echoServPort, efp);
    if(servSock == 0){
      LogDie(efp, "Failed to open sockect connection on port %d\n", echoServPort);
    }else{
      LogMessage(afp, "Successfully listening on port %d\n", echoServPort); 
    }

    processID = fork();

    if (processID < 0){
       LogMessage(efp, "fork() failed.\n");
    } else if (processID == 0) { /* If this is the child process */
       LogMessage(afp, "Forked with processID %d\n", processID);
       WritePidFile(pidpath, execname );
       ProcessMain(servSock, afp, efp);
    }

    LogMessage(afp, "Exiting parent process.\n");
    exit(0);  /* The child will carry on, while the parent exists out gracefully */
}
Esempio n. 8
0
void SpawnApplyConfig(const char *Config, int Flags)
{
char *User=NULL, *Group=NULL, *Dir=NULL;
char *Name=NULL, *Value=NULL;
const char *ptr;
struct rlimit limit;
rlim_t val;

int i;

//set all signal handlers to default
if (Flags & SPAWN_SIGDEF)
{
for (i =0; i < _NSIG; i++) signal(i,SIG_DFL);
}

//Set controlling tty to be stdin. This means that CTRL-C, SIGWINCH etc is handled for the 
//stdin file descriptor, not for any oher 
if (Flags & SPAWN_DAEMON) demonize();
else
{
	if (Flags & SPAWN_SETSID) setsid();
	if (Flags & SPAWN_CTRL_TTY) tcsetpgrp(0, getpgrp());
}

User=CopyStr(User,"");
Group=CopyStr(Group,"");
ptr=GetNameValuePair(Config,"\\S","=",&Name,&Value);
while (ptr)
{
	if (strcasecmp(Name,"User")==0) User=CopyStr(User, Value);
	else if (strcasecmp(Name,"Group")==0) Group=CopyStr(Group, Value);
	else if (strcasecmp(Name,"Dir")==0) Dir=CopyStr(Dir, Value);
	else if (strcasecmp(Name,"PidFile")==0) WritePidFile(Value);
	else if (strcasecmp(Name,"prio")==0) setpriority(PRIO_PROCESS, 0, atoi(Value));
	else if (strcasecmp(Name,"nice")==0) setpriority(PRIO_PROCESS, 0, atoi(Value));
	else if (strcasecmp(Name,"priority")==0) setpriority(PRIO_PROCESS, 0, atoi(Value));
	else if (strcasecmp(Name,"mem")==0) 
	{
		val=(rlim_t) ParseHumanReadableDataQty(Value, 0);
		limit.rlim_cur=val;
		limit.rlim_max=val;
		setrlimit(RLIMIT_DATA, &limit);
	}
	else if (strcasecmp(Name,"fsize")==0) 
	{
		val=(rlim_t) ParseHumanReadableDataQty(Value, 0);
		limit.rlim_cur=val;
		limit.rlim_max=val;
		setrlimit(RLIMIT_FSIZE, &limit);
	}
	else if (strcasecmp(Name,"files")==0) 
	{
		val=(rlim_t) ParseHumanReadableDataQty(Value, 0);
		limit.rlim_cur=val;
		limit.rlim_max=val;
		setrlimit(RLIMIT_NOFILE, &limit);
	}
	else if (strcasecmp(Name,"coredumps")==0) 
	{
		val=(rlim_t) ParseHumanReadableDataQty(Value, 0);
		limit.rlim_cur=val;
		limit.rlim_max=val;
		setrlimit(RLIMIT_CORE, &limit);
	}
	else if ( (strcasecmp(Name,"procs")==0) || (strcasecmp(Name,"nproc")==0) )
	{
		val=(rlim_t) ParseHumanReadableDataQty(Value, 0);
		limit.rlim_cur=val;
		limit.rlim_max=val;
		setrlimit(RLIMIT_NPROC, &limit);
	}
	ptr=GetNameValuePair(ptr,"\\S","=",&Name,&Value);
}

// This allows us to chroot into a whole different unix directory tree, with its own
// password file etc
if (Flags & SPAWN_CHROOT) chroot(".");

if (StrLen(Dir)) chdir(Dir);

//Always do group first, otherwise we'll lose ability to switch user/group
if (StrLen(Group)) SwitchGroup(Group);
if (StrLen(User)) SwitchUser(User);

//Must do this last! After parsing Config, and also after functions like
//SwitchUser that will need access to /etc/passwd
if (Flags & SPAWN_JAIL) chroot(".");

DestroyString(Name);
DestroyString(Value);
DestroyString(User);
DestroyString(Group);
DestroyString(Dir);
}
Esempio n. 9
0
/**
 * Entry point 
 */
int
main(int argc, char** argv )
{
  // TODO ([email protected]) put init settings in ctor
  ApplicationConfig config;
  config.print_debug = false;
  config.is_logging = true;

  SetSignalHandlers();

#ifdef LOG
      logging_init(createTimestampedLogFilename(PANTHEIOS_FE_PROCESS_IDENTITY).c_str());
#endif

  if (capk::InitializeZMQPublisher(&g_zmq_context, &g_pub_socket) != 0) {
#ifdef LOG
    pan::log_CRITICAL("Can't init ZMQ - exiting");
#endif
    return (-1);
  }

  // Must call this to use protobufs
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  // First read command line
  if (ReadCommandLineParams(argc, argv, &config) != 0) {
#ifdef LOG
    pan::log_CRITICAL("Aborting due to missing parameters.");
#endif
    return (-1);
  }

  // Read the symbols to subscribe to from file
  std::vector<std::string> symbols = capk::readSymbolsFile(config.symbol_file_name);
  if (symbols.size() <= 0) {
#ifdef LOG
    pan::log_CRITICAL("No symbols set in:", config.symbol_file_name.c_str());
#endif
    return (-1);
  }

  try {
    FIX::SessionSettings settings(config.config_file_name);
    std::set<FIX::SessionID> sessions = settings.getSessions();
    assert(sessions.size() == 1);
    FIX::SessionID sessionId = *(sessions.begin());
    const FIX::Dictionary& dict = settings.get(sessionId);


    // Get additional config settings from FIX config file
    if (ReadFIXConfig(&config, dict) != 0) {
      fprintf(stderr, "Can't read local config file - exiting\n");
      return (-1);
    }

    if (config.venue_config_file_name == "") {
      // Get config settings from config server
      if (ReadRemoteConfig(&config) != 0) {
        fprintf(stderr, "Can't read remote configuration - exiting\n");
        return (-1);
      }
    }
    else {
      // Get config settings from local ini file
      if (ReadLocalVenueConfig(config.venue_config_file_name, &config) != 0) {
        fprintf(stderr, "Can't read local venue configuration - exiting\n");
        return (-1);
      }
    }

    PrintConfig(&config);

    // Create the FIX application instance
    Application application(config);
    g_papplication = &application;
    application.addSymbols(symbols);

    // Create the output directories for orderbooks, log, and store if needed.
    // Note that actual log directories are created in the location specified
    // with -o arg each time the program starts
    // @TODO ([email protected]) Maybe better to put
    // each log in the dated directory rather than have store and
    // log on same level as dated tick dirs
    if (config.root_output_dir.length() > 0) {
      fs::path argPath = fs::path(config.root_output_dir);
      if (!fs::exists(argPath)) {
        fs::create_directories(argPath);
      }

      fs::path fix_log_path = argPath / fs::path("log");
      if (!fs::exists(fix_log_path)) {
        fs::create_directory(fix_log_path);
      }
      config.fix_log_output_dir = fix_log_path.string();

      fs::path store_path = argPath / fs::path("store");
      if (!fs::exists(store_path)) {
        fs::create_directory(store_path);
      }
      config.fix_store_output_dir = store_path.string();
    }

    pid_t pid = getpid();
    pid_t ppid = getppid();

#ifdef LOG
    pan::log_DEBUG("pid: ", pan::integer(pid), " ppid: ", pan::integer(ppid));
#endif
    if (WritePidFile(argv[0], config.mic_string.c_str(), pid, ppid) != 0) {
#ifdef LOG
      pan::log_CRITICAL("Can't write pid file - exiting");
#endif
      return (-1);
    }

    // Set ZMQ parameters in Application 
    if (config.is_publishing) {
      zmq_bind(g_pub_socket, config.publishing_addr.c_str());
      application.setZMQContext(g_zmq_context);
      application.setZMQSocket(g_pub_socket);
    }


    if (config.is_logging) {
      std::cout << "Logging with FileStoreFactory" << std::endl;
      FIX::FileStoreFactory fileStoreFactory(config.fix_store_output_dir);
      FIX::FileLogFactory logFactory(config.fix_log_output_dir);
      g_pinitiator = new FIX::SocketInitiator(application,
                                              fileStoreFactory,
                                              settings,
                                              logFactory);
      assert(g_pinitiator);
    } else {
      std::cout << "Logging with NullStoreFactory" << std::endl;
      FIX::NullStoreFactory nullStoreFactory;
      g_pinitiator = new FIX::SocketInitiator(application,
                                              nullStoreFactory,
                                              settings);
      assert(g_pinitiator);
    }

    std::cout << "Starting initiator" << std::endl;
    g_pinitiator->start();

    char x;
    std::cout << "Type 'q' to disconnect and exit" << std::endl;
    while (std::cin >> x) {
      if (x == 'q') {
        break;
      }
    }
    std::cout << "Cleaning up" << std::endl;
    g_pinitiator->stop();
    return 0;
  } catch(FIX::Exception& e) {
    std::cerr << e.what();
    return 1;
  }
}
Esempio n. 10
0
/**
 * CCore
 *
 * Creates a new shroudBNC application object.
 *
 * @param Config the main config object
 * @param argc argument counts
 * @param argv program arguments
 */
CCore::CCore(CConfig *Config, int argc, char **argv) {
	int i;

	m_Log = NULL;

	m_PidFile = NULL;

	WritePidFile();

	m_Config = Config;

	m_SSLContext = NULL;
	m_SSLClientContext = NULL;

	m_Status = Status_Running; 

	CacheInitialize(m_ConfigCache, Config, "system.");

	char *SourcePath = strdup(BuildPathLog("sbnc.log"));
	rename(SourcePath, BuildPathLog("sbnc.log.old"));
	free(SourcePath);

	m_PollFds.Preallocate(SFD_SETSIZE);

	m_Log = new CLog("sbnc.log", true);

	if (m_Log == NULL) {
		printf("Log system could not be initialized. Shutting down.");

		exit(EXIT_FAILURE);
	}

	m_Log->Clear();
	Log("Log system initialized.");

	g_Bouncer = this;

	m_Config = Config;

	m_Args.SetList(argv, argc);

	m_Ident = new CIdentSupport();

	m_Config = new CConfig("sbnc.conf", NULL);
	CacheInitialize(m_ConfigCache, m_Config, "system.");

	const char *Users;
	CUser *User;

	if ((Users = m_Config->ReadString("system.users")) == NULL) {
		if (!MakeConfig()) {
			Log("Configuration file could not be created.");

			Fatal();
		}

		printf("Configuration has been successfully saved. Please restart shroudBNC now.\n");
		exit(EXIT_SUCCESS);
	}

	const char *Args;
	int Count;

	Args = ArgTokenize(Users);

	if (AllocFailed(Args)) {
		Fatal();
	}

	Count = ArgCount(Args);

	for (i = 0; i < Count; i++) {
		const char *Name = ArgGet(Args, i + 1);

		User = new CUser(Name);

		if (AllocFailed(User)) {
			Fatal();
		}

		m_Users.Add(Name, User);
	}

	ArgFree(Args);

	m_Listener = NULL;
	m_ListenerV6 = NULL;
	m_SSLListener = NULL;
	m_SSLListenerV6 = NULL;

	time(&m_Startup);

	m_LoadingModules = false;
	m_LoadingListeners = false;

	InitializeSocket();

	m_Capabilities = new CVector<const char *>();
	m_Capabilities->Insert("multi-prefix");
	m_Capabilities->Insert("znc.in/server-time-iso");
}
Esempio n. 11
0
/**
 * StartMainLoop
 *
 * Executes shroudBNC's main loop.
 */
void CCore::StartMainLoop(bool ShouldDaemonize) {
	unsigned int i;

	time(&g_CurrentTime);

	int Port = CacheGetInteger(m_ConfigCache, port);
#ifdef HAVE_LIBSSL
	int SSLPort = CacheGetInteger(m_ConfigCache, sslport);

	if (Port == 0 && SSLPort == 0) {
#else
	if (Port == 0) {
#endif
		Port = 9000;
	}

	const char *BindIp = CacheGetString(m_ConfigCache, ip);

	if (m_Listener == NULL) {
		if (Port != 0) {
			m_Listener = new CClientListener(Port, BindIp, AF_INET);
		} else {
			m_Listener = NULL;
		}
	}

	if (m_ListenerV6 == NULL) {
		if (Port != 0) {
			m_ListenerV6 = new CClientListener(Port, BindIp, AF_INET6);

			if (m_ListenerV6->IsValid() == false) {
				delete m_ListenerV6;

				m_ListenerV6 = NULL;
			}
		} else {
			m_ListenerV6 = NULL;
		}
	}

#ifdef HAVE_LIBSSL
	if (m_SSLListener == NULL) {
		if (SSLPort != 0) {
			m_SSLListener = new CClientListener(SSLPort, BindIp, AF_INET, true);
		} else {
			m_SSLListener = NULL;
		}
	}

	if (m_SSLListenerV6 == NULL) {
		if (SSLPort != 0) {
			m_SSLListenerV6 = new CClientListener(SSLPort, BindIp, AF_INET6, true);

			if (m_SSLListenerV6->IsValid() == false) {
				delete m_SSLListenerV6;

				m_SSLListenerV6 = NULL;
			}
		} else {
			m_SSLListenerV6 = NULL;
		}
	}

	SSL_library_init();
	SSL_load_error_strings();

	SSL_METHOD *SSLMethod = (SSL_METHOD *)SSLv23_method();

	m_SSLContext = SSL_CTX_new(SSLMethod);
	SSL_CTX_set_passwd_cb(m_SSLContext);

	m_SSLClientContext = SSL_CTX_new(SSLMethod);
	SSL_CTX_set_passwd_cb(m_SSLClientContext);

	SSL_CTX_set_mode(m_SSLContext, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
	SSL_CTX_set_mode(m_SSLClientContext, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

	g_SSLCustomIndex = SSL_get_ex_new_index(0, (void *)"CConnection*", NULL, NULL, NULL);

	if (!SSL_CTX_use_PrivateKey_file(m_SSLContext, BuildPathConfig("sbnc.key"), SSL_FILETYPE_PEM)) {
		if (SSLPort != 0) {
			Log("Could not load private key (sbnc.key).");
			ERR_print_errors_fp(stdout);
			return;
		} else {
			SSL_CTX_free(m_SSLContext);
			m_SSLContext = NULL;
		}
	} else {
		SSL_CTX_set_verify(m_SSLContext, SSL_VERIFY_PEER, SSLVerifyCertificate);
	}

	if (!SSL_CTX_use_certificate_chain_file(m_SSLContext, BuildPathConfig("sbnc.crt"))) {
		if (SSLPort != 0) {
			Log("Could not load public key (sbnc.crt).");
			ERR_print_errors_fp(stdout);
			return;
		} else {
			SSL_CTX_free(m_SSLContext);
			m_SSLContext = NULL;
		}
	} else {
		SSL_CTX_set_verify(m_SSLClientContext, SSL_VERIFY_PEER, SSLVerifyCertificate);
	}
#endif

	if (Port != 0 && m_Listener != NULL && m_Listener->IsValid()) {
		Log("Created main listener.");
	} else if (Port != 0) {
		Log("Could not create listener port");
		return;
	}

#ifdef HAVE_LIBSSL
	if (SSLPort != 0 && m_SSLListener != NULL && m_SSLListener->IsValid()) {
		Log("Created ssl listener.");
	} else if (SSLPort != 0) {
		Log("Could not create ssl listener port");
		return;
	}
#endif

	InitializeAdditionalListeners();

	Log("Starting main loop.");

	if (ShouldDaemonize) {
#ifndef _WIN32
		fprintf(stderr, "Daemonizing... ");

		UnlockPidFile();

		if (Daemonize()) {
			fprintf(stderr, "DONE\n");
		} else {
			fprintf(stderr, "FAILED\n");
		}

		WritePidFile();
#endif
	}

	/* Note: We need to load the modules after using fork() as otherwise tcl cannot be cleanly unloaded */
	m_LoadingModules = true;

#ifdef _MSC_VER
	LoadModule("bnctcl.dll");
    LoadModule("bncidentd.dll");
#else
	LoadModule("libbnctcl.la");
#endif

	char *Out;

	i = 0;
	while (true) {
		int rc = asprintf(&Out, "system.modules.mod%d", i++);

		if (RcFailed(rc)) {
			Fatal();
		}

		const char *File = m_Config->ReadString(Out);

		free(Out);

		if (File == NULL) {
			break;
		}

		LoadModule(File);
	}

	m_LoadingModules = false;

	i = 0;
	while (hash_t<CUser *> *User = m_Users.Iterate(i++)) {
		User->Value->LoadEvent();
	}

	int m_ShutdownLoop = 5;

	time_t Last = 0;

	while (GetStatus() == Status_Running || --m_ShutdownLoop) {
		time_t Now, Best = 0, SleepInterval = 0;

#if defined(_WIN32) && defined(_DEBUG)
		DWORD TickCount = GetTickCount();
#endif

		time(&Now);

		i = 0;
		while (hash_t<CUser *> *UserHash = m_Users.Iterate(i++)) {
			CIRCConnection *IRC;

			if ((IRC = UserHash->Value->GetIRCConnection()) != NULL) {
				if (GetStatus() != Status_Running) {
					Log("Closing connection for user %s", UserHash->Name);
					IRC->Kill("Shutting down.");

					UserHash->Value->SetIRCConnection(NULL);
				}

				if (IRC->ShouldDestroy()) {
					IRC->Destroy();
				}
			}
		}

		CUser::RescheduleReconnectTimer();

		time(&Now);

		if (g_CurrentTime - 5 > Now) {
			Log("Time warp detected: %d seconds", Now - g_CurrentTime);
		}

		g_CurrentTime = Now;

		Best = CTimer::GetNextCall();

		if (Best <= g_CurrentTime) {
#ifdef _DEBUG
			if (g_CurrentTime - 1 > Best) {
#else
			if (g_CurrentTime - 5 > Best) {
#endif
				Log("Time warp detected: %d seconds", g_CurrentTime - Best);
			}

			CTimer::CallTimers();

			Best = CTimer::GetNextCall();
		}

		SleepInterval = Best - g_CurrentTime;

		DnsSocketCookie *DnsCookie = CDnsQuery::RegisterSockets();

		for (CListCursor<socket_t> SocketCursor(&m_OtherSockets); SocketCursor.IsValid(); SocketCursor.Proceed()) {
			if (SocketCursor->PollFd->fd == INVALID_SOCKET) {
				continue;
			}

			if (SocketCursor->Events->ShouldDestroy()) {
				SocketCursor->Events->Destroy();
			} else {
				SocketCursor->PollFd->events = POLLIN | POLLERR;

				if (SocketCursor->Events->HasQueuedData()) {
					SocketCursor->PollFd->events |= POLLOUT;
				}
			}
		}

		bool ModulesBusy = false;

	        for (int j = 0; j < m_Modules.GetLength(); j++) {
        	        if (m_Modules[j]->MainLoop()) {
                	        ModulesBusy = true;
	                }
	        }

		if (SleepInterval <= 0 || GetStatus() != Status_Running || ModulesBusy) {
			SleepInterval = 1;
		}

		if (GetStatus() != Status_Running && SleepInterval > 3) {
			SleepInterval = 3;
		}

		timeval interval = { (long)SleepInterval, 0 };

		time(&Last);

#ifdef _DEBUG
		//printf("poll: %d seconds\n", SleepInterval);
#endif

#if defined(_WIN32) && defined(_DEBUG)
		DWORD TimeDiff = GetTickCount();
#endif

		int ready = poll(m_PollFds.GetList(), m_PollFds.GetLength(), interval.tv_sec * 1000);

#if defined(_WIN32) && defined(_DEBUG)
		TickCount += GetTickCount() - TimeDiff;
#endif

		time(&g_CurrentTime);

		if (ready > 0) {
			for (CListCursor<socket_t> SocketCursor(&m_OtherSockets); SocketCursor.IsValid(); SocketCursor.Proceed()) {
				pollfd *PollFd = SocketCursor->PollFd;
				CSocketEvents *Events = SocketCursor->Events;

				if (PollFd->fd != INVALID_SOCKET) {
					if (PollFd->revents & (POLLERR|POLLHUP|POLLNVAL)) {
						int ErrorCode;
						socklen_t ErrorCodeLength = sizeof(ErrorCode);

						ErrorCode = 0;

						if (getsockopt(PollFd->fd, SOL_SOCKET, SO_ERROR, (char *)&ErrorCode, &ErrorCodeLength) != -1) {
							if (ErrorCode != 0) {
								Events->Error(ErrorCode);
							}
						}

						if (ErrorCode == 0) {
							Events->Error(-1);
						}

						Events->Destroy();

						continue;
					}

					if (PollFd->revents & (POLLIN|POLLPRI)) {
						int Code;
						if ((Code = Events->Read()) != 0) {
							Events->Error(Code);
							Events->Destroy();

							continue;
						}
					}

					if (PollFd->revents & POLLOUT) {
						Events->Write();
					}
				}
			}
		} else if (ready == -1) {
#ifndef _WIN32
			if (errno != EBADF && errno != 0) {
#else
			if (errno != WSAENOTSOCK) {
#endif
				continue;
			}

			m_OtherSockets.Lock();

			for (CListCursor<socket_t> SocketCursor(&m_OtherSockets); SocketCursor.IsValid(); SocketCursor.Proceed()) {
				if (SocketCursor->PollFd->fd == INVALID_SOCKET) {
					continue;
				}

				pollfd pfd;
				pfd.fd = SocketCursor->PollFd->fd;
				pfd.events = POLLIN | POLLOUT | POLLERR;

				int code = poll(&pfd, 1, 0);

				if (code == -1) {
					SocketCursor->Events->Error(-1);
					SocketCursor->Events->Destroy();
				}
			}
		}

		CDnsQuery::ProcessTimeouts();
		CDnsQuery::UnregisterSockets(DnsCookie);

#if defined(_WIN32) && defined(_DEBUG)
		DWORD Ticks = GetTickCount() - TickCount;

		if (Ticks > 50) {
			printf("Spent %d msec in the main loop.\n", Ticks);
		}
#endif
	}

#ifdef HAVE_LIBSSL
	SSL_CTX_free(m_SSLContext);
	SSL_CTX_free(m_SSLClientContext);
#endif
}

/**
 * GetUser
 *
 * Returns a user object for the specified username (or NULL
 * if there's no such user).
 *
 * @param Name the username
 */
CUser *CCore::GetUser(const char *Name) {
	if (Name == NULL) {
		return NULL;
	} else {
		return m_Users.Get(Name);
	}
}

/**
 * GlobalNotice
 *
 * Sends a message to all bouncer users who are currently
 * logged in.
 *
 * @param Text the text of the message
 */
void CCore::GlobalNotice(const char *Text) {
	int i = 0;
	char *GlobalText;

	int rc = asprintf(&GlobalText, "Global admin message: %s", Text);

	if (RcFailed(rc)) {
		return;
	}

	while (hash_t<CUser *> *User = m_Users.Iterate(i++)) {
		if (User->Value->GetClientConnectionMultiplexer() != NULL) {
			User->Value->GetClientConnectionMultiplexer()->Privmsg(GlobalText);
		} else {
			User->Value->Log("%s", GlobalText);
		}
	}

	free(GlobalText);
}

/**
 * GetUsers
 *
 * Returns a hashtable which contains all bouncer users.
 */
CHashtable<CUser *, false> *CCore::GetUsers(void) {
	return &m_Users;
}

/**
 * SetIdent
 *
 * Sets the ident which is returned for the next ident request.
 *
 * @param Ident the ident
 */
void CCore::SetIdent(const char *Ident) {
	if (m_Ident != NULL) {
		m_Ident->SetIdent(Ident);
	}
}

/**
 * GetIdent
 *
 * Returns the ident which is to be returned for the next ident
 * request.
 */
const char *CCore::GetIdent(void) const {
	if (m_Ident != NULL) {
		return m_Ident->GetIdent();
	} else {
		return NULL;
	}
}

/**
 * GetModules
 *
 * Returns a list of currently loaded modules.
 */
const CVector<CModule *> *CCore::GetModules(void) const {
	return &m_Modules;
}

/**
 * LoadModule
 *
 * Attempts to load a bouncer module.
 *
 * @param Filename the module's filename
 */
RESULT<CModule *> CCore::LoadModule(const char *Filename) {
	RESULT<bool> Result;

	CModule *Module = new CModule(Filename);

	if (AllocFailed(Module)) {
		THROW(CModule *, Generic_OutOfMemory, "new operator failed.");
	}

	Result = Module->GetError();

	if (!IsError(Result)) {
		Result = m_Modules.Insert(Module);

		if (IsError(Result)) {
			delete Module;

			Log("Insert() failed. Could not load module");

			THROWRESULT(CModule *, Result);
		}

		Log("Loaded module: %s", Module->GetFilename());

		Module->Init(this);

		if (!m_LoadingModules) {
			UpdateModuleConfig();
		}

		RETURN(CModule *, Module);
	} else {
		static char *ErrorString = NULL;

		free(ErrorString);

		ErrorString = strdup(GETDESCRIPTION(Result));

		if (AllocFailed(ErrorString)) {
			delete Module;

			THROW(CModule *, Generic_OutOfMemory, "strdup() failed.");
		}

		Log("Module %s could not be loaded: %s", Filename, ErrorString);

		delete Module;

		THROW(CModule *, Generic_Unknown, ErrorString);
	}

	THROW(CModule *, Generic_Unknown, NULL);
}

/**
 * UnloadModule
 *
 * Unloads a module.
 *
 * @param Module the module
 */
bool CCore::UnloadModule(CModule *Module) {
	if (m_Modules.Remove(Module)) {
		Log("Unloaded module: %s", Module->GetFilename());

		delete Module;

		UpdateModuleConfig();

		return true;
	} else {
		return false;
	}
}

/**
 * UpdateModuleConfig
 *
 * Updates the module list in the main config.
 */
void CCore::UpdateModuleConfig(void) {
	char *Out;
	int a = 0, rc;

	for (int i = 0; i < m_Modules.GetLength(); i++) {
		rc = asprintf(&Out, "system.modules.mod%d", a++);

		if (RcFailed(rc)) {
			Fatal();
		}

		m_Config->WriteString(Out, m_Modules[i]->GetFilename());

		free(Out);
	}

	rc = asprintf(&Out, "system.modules.mod%d", a);

	if (RcFailed(rc)) {
		Fatal();
	}

	m_Config->WriteString(Out, NULL);

	free(Out);
}
Esempio n. 12
0
bool Master::Run(int /*argc*/, char** /*argv*/)
{
    char* config_file = (char*)CONFDIR "/world.conf";

    UNIXTIME = time(NULL);
    g_localTime = *localtime(&UNIXTIME);

    AscLog.InitalizeLogFiles("world");

    PrintBanner();

    LogDefault("The key combination <Ctrl-C> will safely shut down the server.");

#ifndef WIN32
    if (geteuid() == 0 || getegid() == 0)
        AscLog.ConsoleLogMajorError("You are running AscEmu as root.", "This is not needed, and may be a possible security risk.", "It is advised to hit CTRL+C now and", "start as a non-privileged user.");
#endif

    InitImplicitTargetFlags();

    ThreadPool.Startup();
    auto startTime = Util::TimeNow();

    new EventMgr;
    new World;

    if (!LoadWorldConfiguration(config_file))
    {
        return false;
    }

    sWorld.loadWorldConfigValues();

    AscLog.SetFileLoggingLevel(worldConfig.log.worldFileLogLevel);
    AscLog.SetDebugFlags(worldConfig.log.worldDebugFlags);

    OpenCheatLogFiles();

    if (!_StartDB())
    {
        Database::CleanupLibs();
        AscLog.~AscEmuLog();
        return false;
    }

    if (!_CheckDBVersion())
    {
        AscLog.~AscEmuLog();
        return false;
    }

    // Initialize Opcode Table
    WorldSession::InitPacketHandlerTable();

    new ScriptMgr;

    if (!sWorld.setInitialWorldSettings())
    {
        LOG_ERROR("SetInitialWorldSettings() failed. Something went wrong? Exiting.");
        AscLog.~AscEmuLog();
        return false;
    }

    sWorld.setWorldStartTime((uint32)UNIXTIME);

    worldRunnable = std::move(std::make_unique<WorldRunnable>());

    _HookSignals();

    ConsoleThread* console = new ConsoleThread();
    ThreadPool.ExecuteTask(console);

    StartNetworkSubsystem();

    sSocketMgr.SpawnWorkerThreads();

    sScriptMgr.LoadScripts();

    if (worldConfig.startup.enableSpellIdDump)
    {
        sScriptMgr.DumpUnimplementedSpells();
    }

    LogDetail("Server : Ready for connections. Startup time: %u ms", Util::GetTimeDifferenceToNow(startTime));

    ThreadPool.ExecuteTask(new GameEventMgr::GameEventMgrThread());

    StartRemoteConsole();

    WritePidFile();

    if (!ChannelMgr::getSingletonPtr())
        new ChannelMgr;

    channelmgr.seperatechannels = worldConfig.server.seperateChatChannels;

    if (!MailSystem::getSingletonPtr())
        new MailSystem;

    uint32_t mailFlags = 0;

    if (worldConfig.mail.isCostsForGmDisabled)
        mailFlags |= MAIL_FLAG_NO_COST_FOR_GM;

    if (worldConfig.mail.isCostsForEveryoneDisabled)
        mailFlags |= MAIL_FLAG_DISABLE_POSTAGE_COSTS;

    if (worldConfig.mail.isDelayItemsDisabled)
        mailFlags |= MAIL_FLAG_DISABLE_HOUR_DELAY_FOR_ITEMS;

    if (worldConfig.mail.isMessageExpiryDisabled)
        mailFlags |= MAIL_FLAG_NO_EXPIRY;

    if (worldConfig.mail.isInterfactionMailEnabled)
        mailFlags |= MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION;

    if (worldConfig.mail.isInterfactionMailForGmEnabled)
        mailFlags |= MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION_GM;

    sMailSystem.config_flags = mailFlags;

    //ThreadPool.Gobble();

    /* Connect to realmlist servers / logon servers */
    new LogonCommHandler();
    sLogonCommHandler.startLogonCommHandler();

    // Create listener
    ListenSocket<WorldSocket> * ls = new ListenSocket<WorldSocket>(worldConfig.listen.listenHost.c_str(), worldConfig.listen.listenPort);
    bool listnersockcreate = ls->IsOpen();
#ifdef WIN32
    if (listnersockcreate)
        ThreadPool.ExecuteTask(ls);
#endif

    ShutdownThreadPools(listnersockcreate);

    _UnhookSignals();

    worldRunnable->threadShutdown();
    worldRunnable = nullptr;

    ThreadPool.ShowStats();
    /* Shut down console system */
    console->stopThread();
    delete console;

    // begin server shutdown

    ShutdownLootSystem();

    // send a query to wake it up if its inactive
    LogNotice("Database : Clearing all pending queries...");

    // kill the database thread first so we don't lose any queries/data
    CharacterDatabase.EndThreads();
    WorldDatabase.EndThreads();

    ls->Close();

    CloseConsoleListener();
    sWorld.saveAllPlayersToDb();

    LogNotice("Network : Shutting down network subsystem.");
#ifdef WIN32
    sSocketMgr.ShutdownThreads();
#endif
    sSocketMgr.CloseAll();

    bServerShutdown = true;
    ThreadPool.Shutdown();

    delete ls;

    sWorld.logoutAllPlayers();

    delete LogonCommHandler::getSingletonPtr();

    LogNotice("AddonMgr : ~AddonMgr()");
#if VERSION_STRING != Cata
    sAddonMgr.SaveToDB();
#endif
    delete AddonMgr::getSingletonPtr();

    LogNotice("AuctionMgr : ~AuctionMgr()");
    delete AuctionMgr::getSingletonPtr();

    LogNotice("LootMgr : ~LootMgr()");
    delete LootMgr::getSingletonPtr();

    LogNotice("MailSystem : ~MailSystem()");
    delete MailSystem::getSingletonPtr();

    LogNotice("World : ~World()");
    delete World::getSingletonPtr();

    sScriptMgr.UnloadScripts();
    delete ScriptMgr::getSingletonPtr();

    LogNotice("ChatHandler : ~ChatHandler()");
    delete ChatHandler::getSingletonPtr();

    LogNotice("EventMgr : ~EventMgr()");
    delete EventMgr::getSingletonPtr();

    LogNotice("Database : Closing Connections...");
    _StopDB();

    LogNotice("Network : Deleting Network Subsystem...");
    delete SocketMgr::getSingletonPtr();
    delete SocketGarbageCollector::getSingletonPtr();

    delete GMCommand_Log;
    delete Anticheat_Log;
    delete Player_Log;

    // remove pid
    if (remove("worldserver.pid") != 0)
    {
        LOG_ERROR("Error deleting file worldserver.pid");
    }
    else
    {
        LOG_DEBUG("File worldserver.pid successfully deleted");
    }

    LogDetail("Shutdown : Shutdown complete.");
    AscLog.~AscEmuLog();

#ifdef WIN32
    WSACleanup();
#endif

    return true;
}