add: Ns_ThreadSetName("-main-");
context: Ns_Main(int argc, char **argv, Ns_ServerInitProc *initProc){    int            i, fd;    char          *config;    Ns_Time 	   timeout;    char	   cwd[PATH_MAX];    Ns_DString	   addr;#ifndef WIN32    int		   uid = 0;    int		   gid = 0;    int		   kill = 0;    int		   debug = 0;    char	  *root = NULL;    char	  *bindargs = NULL;    char	  *bindfile = NULL;    struct rlimit  rl;#endif    static int	   mode = 0;    /*     * Set up logging defaults (for Ns_Log at startup time).     */    Ns_ThreadSetName("-main-");    nsconf.log.dev       = NS_FALSE;    nsconf.log.debug     = NS_FALSE;    nsconf.log.expanded  = NS_FALSE;    nsconf.log.maxback   = 10;    /*     * When run as a Win32 service, Ns_Main will be re-entered     * in the service main thread.  In this case, jump past     * the point where the initial thread blocked when     * connected to the service control manager.     */     #ifdef WIN32    if (mode == 'S') {    	goto contservice;    }#endif    /*     * AOLserver requires file descriptor 0 be open on /dev/null to     * ensure the server never blocks reading stdin.     */         fd = open(DEVNULL, O_RDONLY|O_TEXT);    if (fd > 0) {    	dup2(fd, 0);	close(fd);    }    /*          * Also, file descriptors 1 and 2 may not be open if the server     * is starting from /etc/init.  If so, open them on /dev/null     * as well because the server will assume they're open during     * initialization.  In particular, the log file will be duped     * to fd's 1 and 2 which would cause problems if 1 and 2     * were open on something important, e.g., the underlying     * SGI sproc-based threads library arena file.     */    fd = open(DEVNULL, O_WRONLY|O_TEXT);    if (fd > 0 && fd != 1) {	close(fd);    }    fd = open(DEVNULL, O_WRONLY|O_TEXT);    if (fd > 0 && fd != 2) {	close(fd);    }#ifndef WIN32    /*     * AOLserver uses select() extensively so adjust the open file     * limit to be no greater than FD_SETSIZE on Unix.  It's possible     * you could define FD_SETSIZE to a larger value and recompile but     * this has not been verified.  Note also that on some platforms     * (e.g., Solaris, SGI o32) you're still left with the hardcoded     * limit of 255  open streams due to the definition of the FILE     * structure with an unsigned char member for the file descriptor.     * Note this limit must be set now to ensure it's inherited by     * all future threads on certain platforms such as SGI and Linux.     */    if (getrlimit(RLIMIT_NOFILE, &rl) != 0) {	Ns_Log(Warning, "nsmain: getrlimit(RLIMIT_NOFILE) failed: '%s'",	       strerror(errno));    } else {	if (rl.rlim_max > FD_SETSIZE) {	    rl.rlim_max = FD_SETSIZE;	}	if (rl.rlim_cur != rl.rlim_max) {    	    rl.rlim_cur = rl.rlim_max;    	    if (setrlimit(RLIMIT_NOFILE, &rl) != 0) {	        Ns_Log(Warning, "nsmain: "		       "setrlimit(RLIMIT_NOFILE, %d) failed: '%s'",		       rl.rlim_max, strerror(errno));	    } 	}    }#endif    /*     * Set defaults and then parse the command line arguments.     */    nsconf.argv0 = argv[0];    nsconf.name = NSD_NAME;    nsconf.version = NSD_VERSION;    time(&nsconf.boot_t);    nsconf.pid = getpid();    nsconf.home = getcwd(cwd, sizeof(cwd));    if (gethostname(nsconf.hostname, sizeof(nsconf.hostname)) != 0) {        strcpy(nsconf.hostname, "localhost");    }    Ns_DStringInit(&addr);    if (Ns_GetAddrByHost(&addr, nsconf.hostname)) {    	strcpy(nsconf.address, addr.string);    }    Ns_DStringFree(&addr);    #ifdef WIN32#define POPTS	"IRS"#else#define POPTS	"kKdr:u:g:b:B:"#endif    opterr = 0;    while ((i = getopt(argc, argv, "qhpzifVs:t:c:" POPTS)) != -1) {        switch (i) {	case 'h':	    UsageError(NULL);	    break;	case 'q':	    nsConfQuiet = 1;	    break;	case 'f':	case 'i':	case 'V':#ifdef WIN32	case 'I':	case 'R':	case 'S':#endif	    if (mode != 0) {		UsageError("only one of -i, -f, -V, -I, -R, or -S may be specified");	    }	    mode = i;	    break;        case 's':	    if (nsServer != NULL) {		UsageError("multiple -s <server> options");	    }	    nsServer = optarg;            break;        case 'c':	    fprintf(stderr, "\nWARNING: -c option is deprecated.  Use translate-ini to convert to tcl (-t) format.\n\n");	case 't':	    if (nsconf.config != NULL) {		UsageError("multiple -t/-c <config> options");	    }            nsconf.config = optarg;	    nsconf.configfmt = i;            break;        case 'z':	    nsMemPools = 1;            break;        case 'p':	    nsMemPools = 0;            break;#ifndef WIN32	case 'b':	    bindargs = optarg;	    break;	case 'B':	    bindfile = optarg;	    break;	case 'r':	    root = optarg;	    break;	case 'K':	case 'k':	    fprintf(stderr, "\nWARNING: -k and -K are deprecated.\n\n");	    if (kill != 0) {		UsageError("only one of -k or -K may be specified");	    }	    kill = i;	    break;        case 'd':	    debug = 1;            break;	case 'g':	    gid = Ns_GetGid(optarg);	    if (gid < 0) {		gid = atoi(optarg);		if (gid == 0) {		    Ns_Fatal("nsmain: invalid group '%s'", optarg);	    	}	    }	    break;	case 'u':	    uid = Ns_GetUid(optarg);	    gid = Ns_GetUserGid(optarg);	    if (uid < 0) {		uid = atoi(optarg);	    }	    if (uid == 0) {		Ns_Fatal("nsmain: invalid user '%s'", optarg);	    }	    break;#endif	case ':':	    sprintf(cwd, "option -%c requires a parameter", optopt);            UsageError(cwd);	    break;        default:	    sprintf(cwd, "invalid option: -%c", optopt);            UsageError(cwd);            break;        }    }    if (mode == 'V') {        printf("AOLserver version %s\n", NSD_VERSION); 	printf("   Platform:        %s\n", Ns_InfoPlatform());	printf("   Built:           %s\n", Ns_InfoBuildDate());	printf("   Tcl version:     %s\n", nsTclVersion);	printf("   Thread library:  %s\n", NsThreadLibName());        return 0;    } else if (nsconf.config == NULL) {        UsageError("required -c/-t <config> option not specified");    }    /*     * Find the absolute config pathname and read the config data.     */    nsconf.config = FindConfig(nsconf.config);    config = NsConfigRead(nsconf.config);#ifndef WIN32        /*     * On Unix, parse non-Tcl style config files in case the     * Unix uid/gid are specified.     */    if (nsconf.configfmt == 'c') {    	NsConfigParse(nsconf.config, config);    }    /*     * Initialize the binder now, before a possible setuid from root     * or chroot which may hide /etc/resolv.conf required to     * bind to one or more ports given on the command line and/or     * pre-bind file.     */    NsInitBinder(bindargs, bindfile);    /*     * Chroot() if requested before setuid from root.     */    if (root != NULL) {	if (chroot(root) != 0) {	    Ns_Fatal("nsmain: chroot(%s) failed: '%s'", root, strerror(errno));	}	if (chdir("/") != 0) {	    Ns_Fatal("nsmain: chdir(/) failed: '%s'", strerror(errno));	}	nsconf.home = "/";    }    /*     * If root, determine and change to the run time user and/or group.     */    if (getuid() == 0) {	char *param;	if (uid == 0 && nsconf.configfmt == 'c') {	    if (!Ns_ConfigGetInt(NS_CONFIG_PARAMETERS, "uid", &uid)) {	    	param = Ns_ConfigGet(NS_CONFIG_PARAMETERS, "user");		if (param != NULL && (uid = Ns_GetUid(param)) < 0) {		    Ns_Fatal("nsmain: no such user '%s'", param);		}	    }	}	if (uid == 0) {	    Ns_Fatal("nsmain: server will not run as root; "		     "must specify '-u username' parameter");	}	if (gid == 0 && nsconf.configfmt == 'c') {	    if (!Ns_ConfigGetInt(NS_CONFIG_PARAMETERS, "gid", &gid)) {	    	param = Ns_ConfigGet(NS_CONFIG_PARAMETERS, "group");	    	if (param != NULL && (gid = Ns_GetGid(param)) < 0) {		    Ns_Fatal("nsmain: no such group '%s'", param);		}	    }	}	/*	 * Before setuid, fork the background binder process to	 * listen on ports which were not pre-bound above.	 */	NsForkBinder();	if (gid != 0 && gid != getgid() && setgid(gid) != 0) {	    Ns_Fatal("nsmain: setgid(%d) failed: '%s'", gid, strerror(errno));	}	if (setuid(uid) != 0) {	    Ns_Fatal("nsmain: setuid(%d) failed: '%s'", uid, strerror(errno));	}    }    /*     * Fork into the background and create a new session if running      * in daemon mode.     */    if (mode == 0) {	i = ns_fork();	if (i < 0) {	    Ns_Fatal("nsmain: fork() failed: '%s'", strerror(errno));	}	if (i > 0) {	    return 0;	}	nsconf.pid = getpid();	setsid();    }    /*     * Finally, block all signals for the duration of startup to ensure any     * new threads inherit the blocked state.     */    NsBlockSignals(debug);#endif    /*     * Initialize Tcl and eval the config file.     */    nsconf.nsd = NsTclFindExecutable(argv[0]);    if (nsconf.configfmt == 't') {    	NsConfigEval(config);    }    ns_free(config);    /*     * Determine the server to run.     */    if (nsServer != NULL) {	if (Ns_ConfigGet(NS_CONFIG_SERVERS, nsServer) == NULL) {	    Ns_Fatal("nsmain: no such server '%s'", nsServer);	}    } else {	Ns_Set *set;	set = Ns_ConfigGetSection(NS_CONFIG_SERVERS);	if (set == NULL || Ns_SetSize(set) != 1) {	    Ns_Fatal("nsmain: no server specified: "		     "specify '-s' parameter or specify "		     NS_CONFIG_SERVERS " in config file");	}	nsServer = Ns_SetKey(set, 0);    }    nsconf.server = nsServer;    /*     * Verify and change to the home directory.     */         nsconf.home = Ns_ConfigGet(NS_CONFIG_PARAMETERS, "home");    if (nsconf.home == NULL) {	Ns_Fatal("nsmain: missing: [%s]home", NS_CONFIG_PARAMETERS);    }    if (chdir(nsconf.home) != 0) {	Ns_Fatal("nsmain: chdir(%s) failed: '%s'", nsconf.home, strerror(errno));    }#ifdef WIN32    /*     * On Win32, first perform some additional cleanup of     * home, ensuring forward slashes and lowercase.     */    nsconf.home = getcwd(cwd, sizeof(cwd));    if (nsconf.home == NULL) {	Ns_Fatal("nsmain: getcwd failed: '%s'", strerror(errno));    }    while (*nsconf.home != '\0') {	if (*nsconf.home == '\\') {	    *nsconf.home = '/';	} else if (isupper(*nsconf.home)) {	    *nsconf.home = tolower(*nsconf.home);	}	++nsconf.home;    }    nsconf.home = cwd;    /*     * Then, connect to the service control manager if running     * as a service (see service comment above).     */    if (mode == 'I' || mode == 'R' || mode == 'S') {	int status;	Ns_ThreadSetName("-service-");	switch (mode) {	case 'I':	    status = NsInstallService();	    break;	case 'R':	    status = NsRemoveService();	    break;	case 'S':    	    status = NsConnectService(initProc);	    break;	}	return (status == NS_OK ? 0 : 1);    }    contservice:#endif    Ns_MutexSetName2(&status.lock, "ns", "status");    /*     * Open the log file now that the home directory and runtime     * user id have been set.     */         if (mode != 'f') {    	NsLogOpen();    }    /*     * On Unix, kill the currently running server if requested.     */     #ifndef WIN32    if (kill != 0) {    	i = NsGetLastPid();	if (i > 0) {    	    NsKillPid(i);	}	if (kill == 'K') {	    return 0;	}    }#endif    /*     * Log the first startup message which should be the first     * output to the open log file.     */         StatusMsg(0);#ifndef WIN32    /*     * Log the current open file limit.     */         if (getrlimit(RLIMIT_NOFILE, &rl) != 0) {	Ns_Log(Warning, "nsmain: "	       "getrlimit(RLIMIT_NOFILE) failed: '%s'", strerror(errno));    } else {	Ns_Log(Notice, "nsmain: "	       "max files: FD_SETSIZE = %d, rl_cur = %d, rl_max = %d",	       FD_SETSIZE, rl.rlim_cur, rl.rlim_max);    }#endif    /*     * Now, call several server initialization routines.  Most of     * these routines simply initialize various data structures but     * some are quite interesting, e.g., NsTclInit() and NsDbInit().     * Also, what happens in NsLoadModules() depends of course on     * the modules loaded, e.g., detached threads, scheduled procs,     * registered URL service procs, etc.     *     * Tcl-wise, this is how server startup goes:     *     * foreach module     *    load .so     * eval private top level files     * eval top level shared where not in private     * foreach module     *    eval private module files     *    eval shared module files where not in private     */    NsProcInit();    NsConfInit();    NsCreatePidFile();    NsGetURLInit();    NsTclInit();    NsCacheInit();    NsDNSInit();    NsInitMimeTypes();    NsInitReturn();    NsInitProxyRequests();    NsInitFastpath();    NsDbInit();    NsAdpInit();    if (initProc != NULL && (*initProc)(nsServer) != NS_OK) {	Ns_Fatal("nsmain: Ns_ServerInitProc failed");    }    NsLoadModules();    NsAdpParsers();        /*     * Eval top level shared/private files, then     * modules' shared/private files.     */        NsTclInitScripts();        /*     * Now that the core server is initialized, stop the child binder     * process (privileged listening ports should not be created at     * run time), start the server listening thread, print the     * "server started" status message, signal the server is     * started for any threads waiting in Ns_WaitForStartup() (e.g.,     * threads blocked in Ns_TclAllocateInterp()), and then run     * any procedures scheduled to run after startup.     */    NsRunPreStartupProcs();    NsStartServer();    NsStartKeepAlive();    NsStartDrivers();#ifndef WIN32    NsStopBinder();#endif    NsTclRunInits();    StatusMsg(1);    Ns_MutexLock(&status.lock);    status.shutdowntimeout = nsconf.shutdowntimeout;    status.started = 1;    Ns_CondBroadcast(&status.cond);    Ns_MutexUnlock(&status.lock);    NsRunStartupProcs();    /*     * Once the listening thread is started, this thread will just     * endlessly wait for Unix signals, calling NsRunSignalProcs()     * whenever SIGHUP arrives.     */    NsHandleSignals();    /*     * Print a "server shutting down" status message and     * then set the nsconf.stopping flag for any threads calling     * Ns_InfoShutdownPending() and then determine an absolute     * timeout for all systems to complete shutown.     */    StatusMsg(2);    Ns_MutexLock(&status.lock);    status.stopping = 1;    if (status.shutdowntimeout < 0) {	status.shutdowntimeout = 0;    }    Ns_GetTime(&timeout);    Ns_IncrTime(&timeout, status.shutdowntimeout, 0);    Ns_MutexUnlock(&status.lock);    /*     * First, stop the drivers and keepalive threads.     */    NsStopDrivers();    NsStopKeepAlive();    NsStopServer(&timeout);    /*     * Next, start and then wait for other systems to shutdown     * simultaneously.  Note that if there was a timeout     * waiting for the connection threads to exit, the following     * waits will generally timeout as well.     */    NsStartSchedShutdown();     NsStartSockShutdown();    NsStartShutdownProcs();    NsWaitSchedShutdown(&timeout);    NsWaitSockShutdown(&timeout);    NsWaitShutdownProcs(&timeout);    /*     * Finally, execute the exit procs directly and print a final     * "server exiting" status message and exit.  Note that     * there is not timeout check for the exit procs so they     * should be well behaved.     */    NsRunAtExitProcs();    NsRemovePidFile();    StatusMsg(3);    return 0;}