Пример #1
0
static void logSecurityDatabaseError(const char* path, ISC_STATUS* status)
{
	const int SHUTDOWN_TIMEOUT = 5000;  // 5 sec

	gds__log_status(path, status);
	gds__put_error(path);
	gds__print_status(status);
	Firebird::Syslog::Record(Firebird::Syslog::Error, "Security database error");
	fb_shutdown(SHUTDOWN_TIMEOUT, fb_shutrsn_exit_called);
	exit(STARTUP_ERROR);
}
Пример #2
0
static void shutdownInit()
{
    setStopMainThread(tryStopMainThread);

    ISC_STATUS_ARRAY status;
    fb_shutdown_callback(status, shutdownInetServer, fb_shut_postproviders, 0);
    if (status[0] == 1 && status[1] > 0)
    {
        gds__log_status("Error in shutdownInit()", status);
        isc_print_status(status);
        exit(STARTUP_ERROR);
    }
}
Пример #3
0
static void logSecurityDatabaseError(const char* path, ISC_STATUS* status)
{
	// If I/O error happened then rather likely we just miss standard security DB
	// Since FB3 with its multiple security databases - not too big trouble
	if (fb_utils::containsErrorCode(status, isc_io_error))
		return;

	const int SHUTDOWN_TIMEOUT = 5000;  // 5 sec

	gds__log_status(path, status);
	gds__put_error(path);
	gds__print_status(status);
	Firebird::Syslog::Record(Firebird::Syslog::Error, "Security database error");
	fb_shutdown(SHUTDOWN_TIMEOUT, fb_shutrsn_exit_called);
	exit(STARTUP_ERROR);
}
Пример #4
0
static THREAD_ENTRY_DECLARE xnet_connect_wait_thread(THREAD_ENTRY_PARAM)
{
/**************************************
 *
 *      x n e t _ c o n n e c t _ w a i t _ t h r e a d
 *
 **************************************
 *
 * Functional description
 *   Starts xnet server side interprocess thread
 *
 **************************************/
	ThreadCounter counter;

	ISC_STATUS_ARRAY status_vector;
	while (!server_shutdown)
	{
		fb_utils::init_status(status_vector);
		rem_port* port = XNET_connect(/*NULL,*/ NULL, status_vector, server_flag);

		if (!port)
		{
			const ISC_STATUS err = status_vector[1];
			if (err)
			{
				if (err == isc_net_server_shutdown)
					break;
				gds__log_status(0, status_vector);
			}
		}
		else if (gds__thread_start(process_connection_thread, port, THREAD_medium, 0, 0))
		{
			gds__log("XNET: can't start worker thread, connection terminated");
			port->disconnect(NULL, NULL);
		}
	}

	return 0;
}
Пример #5
0
static THREAD_ENTRY_DECLARE inet_connect_wait_thread(THREAD_ENTRY_PARAM)
{
/**************************************
 *
 *      i n e t _ c o n n e c t _ w a i t _ t h r e a d
 *
 **************************************
 *
 * Functional description
 *
 **************************************/
	ThreadCounter counter;

	ISC_STATUS_ARRAY status_vector;
	while (!server_shutdown)
	{
		fb_utils::init_status(status_vector);
		rem_port* port = INET_connect(protocol_inet, NULL, status_vector, server_flag, 0);

		if (!port)
		{
			if (status_vector[1]) {
				gds__log_status(0, status_vector);
			}
			break;
		}
		if (server_flag & SRVR_multi_client)
		{
			SRVR_multi_thread(port, server_flag);
			break;
		}
		if (gds__thread_start(process_connection_thread, port, THREAD_medium, 0, 0))
		{
			gds__log("INET: can't start worker thread, connection terminated");
			port->disconnect(NULL, NULL);
		}
	}
	return 0;
}
Пример #6
0
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs, int nWndMode)
{
/**************************************
 *
 *      W i n M a i n
 *
 **************************************
 *
 * Functional description
 *      Run the server with NT named
 *      pipes and/or TCP/IP sockets.
 *
 **************************************/
	hInst = hThisInst;

	// We want server to crash without waiting for feedback from the user
	try
	{
		if (!Config::getBugcheckAbort())
			SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
	}
	catch (Firebird::fatal_exception& e)
	{
		MessageBox(NULL, e.what(), "Firebird server failure",
			MB_OK | MB_ICONHAND | MB_SYSTEMMODAL  | MB_DEFAULT_DESKTOP_ONLY);
		return STARTUP_ERROR; // see /jrd/common.h
	}
	catch (Firebird::status_exception& e)
	{
		TEXT buffer[BUFFER_LARGE];
		const ISC_STATUS* vector = e.value();
		if (! (vector && fb_interpret(buffer, sizeof(buffer), &vector)))
		{
			strcpy(buffer, "Unknown internal failure");
		}

		MessageBox(NULL, buffer, "Firebird server failure",
			MB_OK | MB_ICONHAND | MB_SYSTEMMODAL  | MB_DEFAULT_DESKTOP_ONLY);
		return STARTUP_ERROR; // see /jrd/common.h
	}

#ifdef SUPERSERVER
	server_flag = SRVR_multi_client;
#else
	server_flag = 0;
#endif

#ifdef SUPERSERVER
	SetProcessAffinityMask(GetCurrentProcess(), static_cast<DWORD>(Config::getCpuAffinityMask()));
#endif

	protocol_inet[0] = 0;
	protocol_wnet[0] = 0;

	strcpy(instance, FB_DEFAULT_INSTANCE);

	const HANDLE connection_handle = parse_args(lpszArgs, &server_flag);

#ifdef SUPERSERVER
	// get priority class from the config file
	int priority = Config::getProcessPriorityLevel();

	// override it, if necessary
	if (server_flag & SRVR_high_priority) {
		priority = 1;
	}

	// set priority class
	if (priority > 0) {
		SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
	}
	else if (priority < 0) {
		SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
	}
#endif

	TEXT mutex_name[MAXPATHLEN];
	fb_utils::snprintf(mutex_name, sizeof(mutex_name), SERVER_MUTEX, instance);
	fb_utils::prefix_kernel_object_name(mutex_name, sizeof(mutex_name));
	CreateMutex(ISC_get_security_desc(), FALSE, mutex_name);

	// Initialize the service

	ISC_signal_init();
	Firebird::FpeControl::maskAll();

	int nReturnValue = 0;
	ISC_STATUS_ARRAY status_vector;
	fb_utils::init_status(status_vector);

	fb_shutdown_callback(0, wait_threads, fb_shut_finish, NULL);

	if (connection_handle != INVALID_HANDLE_VALUE)
	{
		rem_port* port = 0;

		if (server_flag & SRVR_inet)
		{
			port = INET_reconnect((SOCKET) connection_handle, status_vector);

			if (port)
			{
				SRVR_multi_thread(port, server_flag);
				port = NULL;
			}
		}
		else if (server_flag & SRVR_wnet)
			port = WNET_reconnect(connection_handle, status_vector);
		else if (server_flag & SRVR_xnet)
			port = XNET_reconnect((ULONG) connection_handle, status_vector);

		if (port) {
			service_connection(port);
		}
		else if (status_vector[1])
			gds__log_status(0, status_vector);

		fb_shutdown(5 * 1000 /*5 seconds*/, fb_shutrsn_no_connection);
	}
	else if (!(server_flag & SRVR_non_service))
	{
		Firebird::string service_name;
		service_name.printf(REMOTE_SERVICE, instance);

		CNTL_init(start_connections_thread, instance);

		const SERVICE_TABLE_ENTRY service_table[] =
		{
			{const_cast<char*>(service_name.c_str()), CNTL_main_thread},
			{NULL, NULL}
		};

		// BRS There is a error in MinGW (3.1.0) headers
		// the parameter of StartServiceCtrlDispatcher is declared const in msvc headers
#if defined(MINGW)
		if (!StartServiceCtrlDispatcher(const_cast<SERVICE_TABLE_ENTRY*>(service_table)))
		{
#else
		if (!StartServiceCtrlDispatcher(service_table))
		{
#endif
			if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) {
				CNTL_shutdown_service("StartServiceCtrlDispatcher failed");
			}
			server_flag |= SRVR_non_service;
		}
	}
	else
	{
		start_connections_thread(0);
		nReturnValue = WINDOW_main(hThisInst, nWndMode, server_flag);
	}

#ifdef DEBUG_GDS_ALLOC
	// In Debug mode - this will report all server-side memory leaks
	// due to remote access

	//gds_alloc_report(0, __FILE__, __LINE__);
	Firebird::PathName name = fb_utils::getPrefix(fb_utils::FB_DIR_LOG, "memdebug.log");
	FILE* file = fopen(name.c_str(), "w+t");
	if (file)
	{
		fprintf(file, "Global memory pool allocated objects\n");
		getDefaultMemoryPool()->print_contents(file);
		fclose(file);
	}
#endif

	return nReturnValue;
}


THREAD_ENTRY_DECLARE process_connection_thread(THREAD_ENTRY_PARAM arg)
{
/**************************************
 *
 *      p r o c e s s _ c o n n e c t i o n _ t h r e a d
 *
 **************************************
 *
 * Functional description
 *
 **************************************/
	ThreadCounter counter;

	service_connection((rem_port*) arg);
	return 0;
}
Пример #7
0
    int FB_EXPORTED server_main( int argc, char** argv)
    {
        /**************************************
         *
         *	m a i n
         *
         **************************************
         *
         * Functional description
         *	Run the server with apollo mailboxes.
         *
         **************************************/
        RemPortPtr port;

// 01 Sept 2003, Nickolay Samofatov
// In GCC version 3.1-3.3 we need to install special error handler
// in order to get meaningful terminate() error message on stderr.
// In GCC 3.4 or later this is the default.
//#if __GNUC__ == 3 && __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4
//    std::set_terminate (__gnu_cxx::__verbose_terminate_handler);
//#endif

        const TEXT* const* const end = argc + argv;
        argv++;
        bool debug = false, standalone = false;
        INET_SERVER_flag = 0;
        int channel = 0;
        protocol[0] = 0;
        bool multi_client = false, multi_threaded = false;

#ifdef SUPERSERVER
        INET_SERVER_flag |= SRVR_multi_client;
        multi_client = multi_threaded = standalone = true;
#endif

        int clients = 0;
        bool done = false;

        while (argv < end)
        {
            TEXT c;
            const TEXT* p = *argv++;
            if (*p++ == '-')
                while (c = *p++)
                {
                    switch (UPPER(c))
                    {
                    case 'D':
                        INET_SERVER_flag |= SRVR_debug;
                        debug = true;
                        break;
#ifndef SUPERSERVER

                    case 'M':
                        INET_SERVER_flag |= SRVR_multi_client;
                        if (argv < end)
                        {
                            if (clients = atoi(*argv))
                                argv++;
                        }
                        multi_client = standalone = true;
                        break;

                    case 'S':
                        standalone = true;
                        break;


                    case 'I':
                        standalone = false;
                        break;

                    case 'T':
                        multi_threaded = true;
                        break;

                    case 'U':
                        multi_threaded = false;
                        break;
#endif // SUPERSERVER

                    case 'E':
                        if (ISC_set_prefix(p, *argv) == -1)
                            printf("Invalid argument Ignored\n");
                        else
                            argv++;	// do not skip next argument if this one is invalid
                        done = true;
                        break;

                    case 'P':
                        fb_utils::snprintf(protocol, sizeof(protocol), "/%s", *argv++);
                        break;

                    case 'H':
                    case '?':
                        printf("Firebird TCP/IP server options are:\n");
                        printf("  -d           : debug on\n");

#ifndef SUPERSERVER
                        // These options are not applicable to super server
                        printf("  -m           : multiclient - on\n");
                        printf("  -s           : standalone - true\n");
                        printf("  -i           : standalone - false\n");

                        printf("  -t           : multithread - true  (non pc only)\n");
                        printf("  -u           : multithread - false (pc only)\n");
#endif

                        printf("  -p<protocol> : specify protocol\n");
                        printf("  -h|? : print this help\n");
                        printf("\n");
                        printf("  (The following -e options used to be -h options)\n");
                        printf("  -e <firebird_root_dir>   : set firebird_root path\n");
                        printf("  -el <firebird_lock_dir>  : set runtime firebird_lock dir\n");
                        printf("  -em <firebird_msg_dir>   : set firebird_msg dir path\n");
                        printf("  -z   : print version\n");

                        exit(FINI_OK);
                    case 'Z':
                        printf("Firebird TCP/IP server version %s\n", GDS_VERSION);
                        exit(FINI_OK);
                    }
                    if (done)
                        break;
                }
        }

        // activate paths set with -e family of switches
        ISC_set_prefix(0, 0);

#ifdef UNIX
        set_signal(SIGPIPE, signal_handler);
        set_signal(SIGUSR1, signal_handler);
        set_signal(SIGUSR2, signal_handler);
#endif

#if defined(UNIX) && defined(HAVE_SETRLIMIT) && defined(HAVE_GETRLIMIT)

#ifdef RLIMIT_NPROC
        raiseLimit(RLIMIT_NPROC);
#endif

#if !(defined(DEV_BUILD))
        if (Config::getBugcheckAbort())
#endif
        {
            // try to force core files creation
            raiseLimit(RLIMIT_CORE);

            // we need some writable directory for core file
            // on any unix /tmp seems to be the best place
            if (CHANGE_DIR(TEMP_DIR))
            {
                // error on changing the directory
                gds__log("Could not change directory to %s due to errno %d", TEMP_DIR, errno);
            }
        }

#if defined(SUPERSERVER) && (defined SOLARIS || defined HPUX || defined LINUX)
        // Increase max open files to hard limit for Unix
        // platforms which are known to have low soft limits.

        raiseLimit(RLIMIT_NOFILE);
#endif

#endif

        // Fork off a server, wait for it to die, then fork off another,
        // but give up after 100 tries

#ifndef SUPERSERVER
        if (multi_client && !debug)
        {
#ifdef UNIX
            set_signal(SIGUSR1, signal_handler);
#endif
            int child;
            for (int n = 0; n < 100; n++)
            {
                INET_SERVER_start = 0;
                if (!(child = fork()))
                    break;
                while (wait(0) != child)
                    if (INET_SERVER_start)
                    {
                        n = 0;		// reset error counter on "real" signal
                        break;
                    }
                gds__log("INET_SERVER/main: gds_inet_server restarted");
            }
#ifdef UNIX
            set_signal(SIGUSR1, SIG_DFL);
#endif
        }
#endif

        if (standalone)
        {
            if (multi_client)
            {
#ifdef SUPERSERVER

                // Remove restriction on username, for DEV builds
                // restrict only for production builds.  MOD 21-July-2002
#ifndef DEV_BUILD
                Firebird::string user_name;	// holds the user name
                // check user id
                ISC_get_user(&user_name, NULL, NULL, NULL);

                if (user_name != "root" &&
                        user_name != FIREBIRD_USER_NAME &&
                        user_name != INTERBASE_USER_NAME &&
                        user_name != INTERBASE_USER_SHORT)
                {
                    // invalid user -- bail out
                    fprintf(stderr, "%s: Invalid user (must be %s, %s, %s or root).\n",
                            "fbserver", FIREBIRD_USER_NAME,
                            INTERBASE_USER_NAME, INTERBASE_USER_SHORT);
                    exit(STARTUP_ERROR);
                }
#endif
#else
                if (setreuid(0, 0) < 0)
                    printf("Inet_server: couldn't set uid to superuser.\n");
#endif
                INET_set_clients(clients);
            }

            if (!debug)
            {
                int mask = 0; // FD_ZERO(&mask);
                mask |= 1 << 2; // FD_SET(2, &mask);
                divorce_terminal(mask);
            }
            {   // scope block
                ISC_STATUS_ARRAY status_vector;
                port = INET_connect(protocol, 0, status_vector, INET_SERVER_flag, 0);
                if (!port)
                {
                    gds__print_status(status_vector);
                    exit(STARTUP_ERROR);
                }
            } // end scope block
        }
        else
        {
            port = INET_server(channel);
            if (!port)
            {
                fprintf(stderr, "fbserver: Unable to start INET_server\n");
                exit(STARTUP_ERROR);
            }
        }

#ifdef SUPERSERVER
        // before starting the superserver stuff change directory to tmp
        if (CHANGE_DIR(TEMP_DIR))
        {
            // error on changing the directory
            gds__log("Could not change directory to %s due to errno %d", TEMP_DIR, errno);
        }

        // Server tries to attach to security2.fdb to make sure everything is OK
        // This code fixes bug# 8429 + all other bug of that kind - from
        // now on the server exits if it cannot attach to the database
        // (wrong or no license, not enough memory, etc.

        {   // scope
            TEXT path[MAXPATHLEN];
            ISC_STATUS_ARRAY status;
            isc_db_handle db_handle = 0L;

            Jrd::SecurityDatabase::getPath(path);
            const char dpb[] = {isc_dpb_version1, isc_dpb_gsec_attach, 1, 1};
            isc_attach_database(status, strlen(path), path, &db_handle, sizeof dpb, dpb);
            if (status[0] == 1 && status[1] > 0)
            {
                gds__log_status(path, status);
                isc_print_status(status);
                exit(STARTUP_ERROR);
            }
            isc_detach_database(status, &db_handle);
            if (status[0] == 1 && status[1] > 0)
            {
                gds__log_status(path, status);
                isc_print_status(status);
                exit(STARTUP_ERROR);
            }
        } // end scope

        shutdownInit();
#endif

        SRVR_multi_thread(port, INET_SERVER_flag);

#ifdef DEBUG_GDS_ALLOC
        // In Debug mode - this will report all server-side memory leaks due to remote access

        //gds_alloc_report(0, __FILE__, __LINE__);
        Firebird::PathName name = fb_utils::getPrefix(fb_utils::FB_DIR_LOG, "memdebug.log");
        FILE* file = fopen(name.c_str(), "w+t");
        if (file)
        {
            fprintf(file, "Global memory pool allocated objects\n");
            getDefaultMemoryPool()->print_contents(file);
            fclose(file);
        }
#endif

        // perform atexit shutdown here when all globals in embedded library are active
        // also sync with possibly already running shutdown in dedicated thread
        fb_shutdown(10000, fb_shutrsn_exit_called);

        return FINI_OK;
    }