CUBRID Engine  latest
server.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * server.c - server main
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <fcntl.h>
30 #include <signal.h>
31 #if defined(WINDOWS)
32 #include <process.h>
33 #include <winsock2.h>
34 #include <windows.h>
35 #include <dbgHelp.h>
36 #include <assert.h>
37 
38 #else /* WINDOWS */
39 #include <sys/resource.h>
40 #include <unistd.h>
41 #include <limits.h>
42 #endif /* WINDOWS */
43 
44 #include "porting.h"
45 #include "system_parameter.h"
46 #include "connection_error.h"
47 #include "network.h"
48 #include "environment_variable.h"
49 #include "boot_sr.h"
50 #include "system_parameter.h"
51 #include "perf_monitor.h"
52 #include "util_func.h"
53 #if defined(WINDOWS)
54 #include "wintcp.h"
55 #else /* !defined (WINDOWS) */
56 #include "tcp.h"
57 #include "heartbeat.h"
58 #include "log_impl.h"
59 #endif /* !defined (WINDOWS) */
60 
61 #if defined(WINDOWS)
62 LONG WINAPI CreateMiniDump (struct _EXCEPTION_POINTERS *pException, char *db_name);
63 #else /* WINDOWS */
64 static void register_fatal_signal_handler (int signo);
65 static void crash_handler (int signo, siginfo_t * siginfo, void *dummyp);
66 #if !defined (NDEBUG)
67 static void abort_handler (int signo, siginfo_t * siginfo, void *dummyp);
68 #endif /* !NDEBUG */
69 #endif /* WINDOWS */
70 
71 static const char *database_name = "";
72 
73 static char executable_path[PATH_MAX];
74 
75 #if !defined(WINDOWS)
76 /*
77  * unmask_signal(): unmask the given signal
78  *
79  * returns: 0 for SUCCESS, -1 for otherwise
80  * signo(IN): signo to handle
81  *
82  */
83 
84 static int
85 unmask_signal (int signo)
86 {
87  sigset_t sigset;
88 
89  sigemptyset (&sigset);
90  sigaddset (&sigset, signo);
91  return sigprocmask (SIG_UNBLOCK, &sigset, NULL);
92 }
93 
94 /*
95  * register_fatal_signal_hander(): register the handler of the given signal
96  *
97  * returns: none
98  * signo(IN): signo to handle
99  *
100  */
101 
102 static void
104 {
105  struct sigaction act;
106 
107  act.sa_handler = NULL;
108  act.sa_sigaction = crash_handler;
109  sigemptyset (&act.sa_mask);
110  act.sa_flags = 0;
111  act.sa_flags |= SA_SIGINFO;
112  sigaction (signo, &act, NULL);
113 }
114 
115 #if !defined (NDEBUG)
116 static void
118 {
119  struct sigaction act;
120 
121  act.sa_handler = NULL;
122  act.sa_sigaction = abort_handler;
123  sigemptyset (&act.sa_mask);
124  act.sa_flags = 0;
125  act.sa_flags |= SA_SIGINFO;
126  sigaction (signo, &act, NULL);
127 }
128 #endif /* !NDEBUG */
129 #endif /* !WINDOWS */
130 
131 #if defined(WINDOWS)
132 
133 LONG WINAPI
134 CreateMiniDump (struct _EXCEPTION_POINTERS *pException, char *db_name)
135 {
136  STARTUPINFO si;
137  PROCESS_INFORMATION pi;
138  BOOL fSuccess;
139  char cmd_line[PATH_MAX];
140  TCHAR DumpFile[MAX_PATH] = { 0, };
141  TCHAR DumpPath[MAX_PATH] = { 0, };
142  SYSTEMTIME SystemTime;
143  HANDLE FileHandle;
144 
145  GetLocalTime (&SystemTime);
146 
147  sprintf (DumpFile, "%d-%d-%d %d_%d_%d.dmp", SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour,
148  SystemTime.wMinute, SystemTime.wSecond);
149  envvar_bindir_file (DumpPath, MAX_PATH, DumpFile);
150 
151  FileHandle = CreateFile (DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
152 
153  if (FileHandle != INVALID_HANDLE_VALUE)
154  {
155  MINIDUMP_EXCEPTION_INFORMATION MiniDumpExceptionInfo;
156  BOOL Success;
157 
158  MiniDumpExceptionInfo.ThreadId = GetCurrentThreadId ();
159  MiniDumpExceptionInfo.ExceptionPointers = pException;
160  MiniDumpExceptionInfo.ClientPointers = FALSE;
161 
162  Success =
163  MiniDumpWriteDump (GetCurrentProcess (), GetCurrentProcessId (), FileHandle, MiniDumpNormal,
164  (pException) ? &MiniDumpExceptionInfo : NULL, NULL, NULL);
165  }
166 
167  CloseHandle (FileHandle);
168 
169  /* restart cub_server.exe */
170  GetStartupInfo (&si);
171 
172  snprintf (cmd_line, PATH_MAX, "\"%s\" \"%s\"", executable_path, db_name);
173 
174  fSuccess = CreateProcess (executable_path, cmd_line,
175  /* Default process security attrs */
176  NULL,
177  /* Default thread security attrs */
178  NULL,
179  /* Don't inherit handles */
180  FALSE,
181  /* normal priority */
182  0,
183  /* Use the same environment as parent */
184  NULL,
185  /* Launch in the current directory */
186  NULL,
187  /* start up information */
188  &si, &pi);
189 
190  return EXCEPTION_EXECUTE_HANDLER;
191 }
192 
193 #else /* WINDOWS */
194 
195 /*
196  * crash_handler(): kill the server and spawn the new server process
197  *
198  * returns: none
199  * signo(IN): signo to handle
200  * siginfo(IN): siginfo struct
201  * dummyp(IN): this argument will not be used,
202  * but remains to cope with its function prototype.
203  *
204  */
205 
206 static void
207 crash_handler (int signo, siginfo_t * siginfo, void *dummyp)
208 {
209  int pid;
210 
211  if (signo != SIGABRT && siginfo != NULL && siginfo->si_code <= 0)
212  {
214  return;
215  }
216 
217  if (os_set_signal_handler (signo, SIG_DFL) == SIG_ERR)
218  {
219  return;
220  }
221 
223  {
224  return;
225  }
226 
227  pid = fork ();
228  if (pid == 0)
229  {
230  char err_log[PATH_MAX];
231  int ppid;
232  int fd, fd_max;
233 
234  fd_max = css_get_max_socket_fds ();
235 
236  for (fd = 3; fd < fd_max; fd++)
237  {
238  close (fd);
239  }
240 
241  ppid = getppid ();
242  while (1)
243  {
244  if (kill (ppid, 0) < 0)
245  {
246  break;
247  }
248  sleep (1);
249  }
250 
251  unmask_signal (signo);
252 
254  {
255  snprintf (err_log, PATH_MAX, "%s.%d", prm_get_string_value (PRM_ID_ER_LOG_FILE), ppid);
256  rename (prm_get_string_value (PRM_ID_ER_LOG_FILE), err_log);
257  }
258 
260  exit (0);
261  }
262 }
263 
264 #if !defined (NDEBUG)
265 static void
266 abort_handler (int signo, siginfo_t * siginfo, void *dummyp)
267 {
268  int *local_clients_pid = NULL;
269  int i, num_clients, client_pid;
270 
271  if (os_set_signal_handler (signo, SIG_DFL) == SIG_ERR)
272  {
273  return;
274  }
275 
276  if (!BO_IS_SERVER_RESTARTED ())
277  {
278  return;
279  }
280 
281  num_clients = logtb_collect_local_clients (&local_clients_pid);
282 
283  for (i = 0; i < num_clients; i++)
284  {
285  client_pid = local_clients_pid[i];
286  if (client_pid == 0)
287  {
288  /* reached the end. */
289  break;
290  }
291 
292  assert (client_pid > 0);
293 
294  kill (client_pid, SIGABRT);
295  }
296 
297  if (local_clients_pid != NULL)
298  {
299  free (local_clients_pid);
300  }
301 
302  /* abort the server itself */
303  abort ();
304 }
305 #endif /* !NDEBUG */
306 #endif /* WINDOWS */
307 
308 /*
309  * main(): server's main function
310  *
311  * returns: 0 for SUCCESS, non-zero for ERROR
312  *
313  */
314 int
315 main (int argc, char **argv)
316 {
317  char *binary_name;
318  int ret_val = 0;
319 
320 #if defined(WINDOWS)
321  FreeConsole ();
322 
323  __try
324 #else /* WINDOWS */
325 #if !defined (NDEBUG)
327 #else
329 #endif
335 #endif /* WINDOWS */
336 
337  { /* to make indent happy */
338  if (argc < 2)
339  {
340  PRINT_AND_LOG_ERR_MSG ("Usage: server databasename\n");
341  return 1;
342  }
343 
344  fprintf (stdout, "\nThis may take a long time depending on the amount " "of recovery works to do.\n");
345 
346  /* save executable path */
347  binary_name = basename (argv[0]);
348  (void) envvar_bindir_file (executable_path, PATH_MAX, binary_name);
349  /* save database name */
350  database_name = argv[1];
351 
352 #if !defined(WINDOWS)
354  hb_set_argv (argv);
355 
356  /* create a new session */
357  setsid ();
358 #endif
359 
360  ret_val = net_server_start (database_name);
361 
362  }
363 #if defined(WINDOWS)
364  __except (CreateMiniDump (GetExceptionInformation (), argv[1]))
365  {
366  }
367 #endif
368  return ret_val;
369 }
static void register_abort_signal_handler(int signo)
Definition: server.c:117
int main(int argc, char **argv)
Definition: server.c:315
#define BO_IS_SERVER_RESTARTED()
Definition: boot_sr.h:84
#define PRINT_AND_LOG_ERR_MSG(...)
Definition: util_func.h:49
int argc
Definition: dynamic_load.c:951
int net_server_start(const char *name)
Definition: network_sr.c:1292
void hb_set_exec_path(char *exec_path)
Definition: heartbeat.c:125
int css_get_max_socket_fds(void)
Definition: tcp.c:1315
static void register_fatal_signal_handler(int signo)
Definition: server.c:103
void hb_set_argv(char **argv)
Definition: heartbeat.c:137
#define assert(x)
static const char * database_name
Definition: server.c:71
static char executable_path[PATH_MAX]
Definition: server.c:73
char * envvar_bindir_file(char *path, size_t size, const char *filename)
#define NULL
Definition: freelistheap.h:34
pid_t pid
Definition: dynamic_load.c:955
static void crash_handler(int signo, siginfo_t *siginfo, void *dummyp)
Definition: server.c:207
char * db_name
int logtb_collect_local_clients(int **local_client_pids)
static int unmask_signal(int signo)
Definition: server.c:85
const char ** argv
Definition: dynamic_load.c:952
char * prm_get_string_value(PARAM_ID prm_id)
bool prm_get_bool_value(PARAM_ID prm_id)
#define FALSE
Definition: broker_admin.c:50
char * basename(const char *path)
Definition: porting.c:1132
int i
Definition: dynamic_load.c:954
static void abort_handler(int signo, siginfo_t *siginfo, void *dummyp)
Definition: server.c:266
SIGNAL_HANDLER_FUNCTION os_set_signal_handler(const int sig_no, SIGNAL_HANDLER_FUNCTION sig_handler)
Definition: porting.c:1333