File server.c¶
File List > cubrid > src > executables > server.c
Go to the documentation of this file
/*
* Copyright 2008 Search Solution Corporation
* Copyright 2016 CUBRID Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* server.c - server main
*/
#ident "$Id$"
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#if defined(WINDOWS)
#include <process.h>
#include <winsock2.h>
#include <windows.h>
#include <dbgHelp.h>
#include <assert.h>
#else /* WINDOWS */
#include <sys/resource.h>
#include <unistd.h>
#include <limits.h>
#endif /* WINDOWS */
#include "porting.h"
#include "system_parameter.h"
#include "connection_error.h"
#include "network.h"
#include "environment_variable.h"
#include "boot_sr.h"
#include "system_parameter.h"
#include "perf_monitor.h"
#include "util_func.h"
#include "connection_sr.h"
#if defined(WINDOWS)
#include "wintcp.h"
#else /* !defined (WINDOWS) */
#include "tcp.h"
#include "heartbeat.h"
#include "log_impl.h"
#endif /* !defined (WINDOWS) */
#if defined(WINDOWS)
LONG WINAPI CreateMiniDump (struct _EXCEPTION_POINTERS *pException, char *db_name);
#else /* WINDOWS */
static void register_fatal_signal_handler (int signo);
static void crash_handler (int signo, siginfo_t * siginfo, void *dummyp);
#if !defined (NDEBUG)
static void abort_handler (int signo, siginfo_t * siginfo, void *dummyp);
#endif /* !NDEBUG */
#endif /* WINDOWS */
static const char *database_name = "";
static char executable_path[PATH_MAX];
#if !defined(WINDOWS)
/*
* unmask_signal(): unmask the given signal
*
* returns: 0 for SUCCESS, -1 for otherwise
* signo(IN): signo to handle
*
*/
static int
unmask_signal (int signo)
{
sigset_t sigset;
sigemptyset (&sigset);
sigaddset (&sigset, signo);
return sigprocmask (SIG_UNBLOCK, &sigset, NULL);
}
/*
* register_fatal_signal_hander(): register the handler of the given signal
*
* returns: none
* signo(IN): signo to handle
*
*/
static void
register_fatal_signal_handler (int signo)
{
struct sigaction act;
act.sa_handler = NULL;
act.sa_sigaction = crash_handler;
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
act.sa_flags |= SA_SIGINFO;
sigaction (signo, &act, NULL);
}
#if !defined (NDEBUG)
static void
register_abort_signal_handler (int signo)
{
struct sigaction act;
act.sa_handler = NULL;
act.sa_sigaction = abort_handler;
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
act.sa_flags |= SA_SIGINFO;
sigaction (signo, &act, NULL);
}
#endif /* !NDEBUG */
#endif /* !WINDOWS */
#if defined(WINDOWS)
LONG WINAPI
CreateMiniDump (struct _EXCEPTION_POINTERS *pException, char *db_name)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL fSuccess;
char cmd_line[PATH_MAX];
TCHAR DumpFile[MAX_PATH] = { 0, };
TCHAR DumpPath[MAX_PATH] = { 0, };
SYSTEMTIME SystemTime;
HANDLE FileHandle;
GetLocalTime (&SystemTime);
sprintf (DumpFile, "%d-%d-%d %d_%d_%d.dmp", SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour,
SystemTime.wMinute, SystemTime.wSecond);
envvar_bindir_file (DumpPath, MAX_PATH, DumpFile);
FileHandle = CreateFile (DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (FileHandle != INVALID_HANDLE_VALUE)
{
MINIDUMP_EXCEPTION_INFORMATION MiniDumpExceptionInfo;
BOOL Success;
MiniDumpExceptionInfo.ThreadId = GetCurrentThreadId ();
MiniDumpExceptionInfo.ExceptionPointers = pException;
MiniDumpExceptionInfo.ClientPointers = FALSE;
Success =
MiniDumpWriteDump (GetCurrentProcess (), GetCurrentProcessId (), FileHandle, MiniDumpNormal,
(pException) ? &MiniDumpExceptionInfo : NULL, NULL, NULL);
}
CloseHandle (FileHandle);
/* restart cub_server.exe */
GetStartupInfo (&si);
snprintf (cmd_line, PATH_MAX, "\"%s\" \"%s\"", executable_path, db_name);
fSuccess = CreateProcess (executable_path, cmd_line,
/* Default process security attrs */
NULL,
/* Default thread security attrs */
NULL,
/* Don't inherit handles */
FALSE,
/* normal priority */
0,
/* Use the same environment as parent */
NULL,
/* Launch in the current directory */
NULL,
/* start up information */
&si, &pi);
return EXCEPTION_EXECUTE_HANDLER;
}
#else /* WINDOWS */
/*
* crash_handler(): kill the server and spawn the new server process
*
* returns: none
* signo(IN): signo to handle
* siginfo(IN): siginfo struct
* dummyp(IN): this argument will not be used,
* but remains to cope with its function prototype.
*
*/
static void
crash_handler (int signo, siginfo_t * siginfo, void *dummyp)
{
if (signo != SIGABRT && siginfo != NULL && siginfo->si_code <= 0)
{
register_fatal_signal_handler (signo);
return;
}
if (os_set_signal_handler (signo, SIG_DFL) == SIG_ERR)
{
return;
}
er_print_crash_callstack (signo);
}
#if !defined (NDEBUG)
static void
abort_handler (int signo, siginfo_t * siginfo, void *dummyp)
{
int *local_clients_pid = NULL;
int i, num_clients, client_pid;
if (os_set_signal_handler (signo, SIG_DFL) == SIG_ERR)
{
return;
}
if (!BO_IS_SERVER_RESTARTED ())
{
return;
}
num_clients = logtb_collect_local_clients (&local_clients_pid);
for (i = 0; i < num_clients; i++)
{
client_pid = local_clients_pid[i];
if (client_pid == 0)
{
/* reached the end. */
break;
}
assert (client_pid > 0);
kill (client_pid, SIGABRT);
}
if (local_clients_pid != NULL)
{
free (local_clients_pid);
}
er_print_crash_callstack (signo);
/* abort the server itself */
abort ();
}
#endif /* !NDEBUG */
#endif /* WINDOWS */
/*
* main(): server's main function
*
* returns: 0 for SUCCESS, non-zero for ERROR
*
*/
int
main (int argc, char **argv)
{
char *binary_name;
int ret_val = 0;
#if defined(WINDOWS)
FreeConsole ();
__try
#else /* WINDOWS */
#if !defined (NDEBUG)
register_abort_signal_handler (SIGABRT);
#else
register_fatal_signal_handler (SIGABRT);
#endif
register_fatal_signal_handler (SIGILL);
register_fatal_signal_handler (SIGFPE);
register_fatal_signal_handler (SIGBUS);
register_fatal_signal_handler (SIGSEGV);
register_fatal_signal_handler (SIGSYS);
#endif /* WINDOWS */
{ /* to make indent happy */
if (argc < 2)
{
PRINT_AND_LOG_ERR_MSG ("Usage: server databasename\n");
return 1;
}
fprintf (stdout, "\nThis may take a long time depending on the amount " "of recovery works to do.\n");
fflush (stdout);
/* save executable path */
binary_name = basename (argv[0]);
(void) envvar_bindir_file (executable_path, PATH_MAX, binary_name);
/* save database name */
database_name = argv[1];
#if !defined(WINDOWS)
hb_set_exec_path (executable_path);
hb_set_argv (argv);
css_set_exec_path (executable_path);
css_set_argv (argv);
/* create a new session */
setsid ();
#endif
ret_val = net_server_start (database_name);
}
#if defined(WINDOWS)
__except (CreateMiniDump (GetExceptionInformation (), argv[1]))
{
}
#endif
return ret_val;
}