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); }
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); } }
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); }
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; }
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; }
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; }
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; }