1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available at through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt. |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: George Wang <gwang@litespeedtech.com> |
16 +----------------------------------------------------------------------+
17 */
18 /*
19 Copyright (c) 2002-2018, Lite Speed Technologies Inc.
20 All rights reserved.
21
22 Redistribution and use in source and binary forms, with or without
23 modification, are permitted provided that the following conditions are
24 met:
25
26 * Redistributions of source code must retain the above copyright
27 notice, this list of conditions and the following disclaimer.
28 * Redistributions in binary form must reproduce the above
29 copyright notice, this list of conditions and the following
30 disclaimer in the documentation and/or other materials provided
31 with the distribution.
32 * Neither the name of the Lite Speed Technologies Inc nor the
33 names of its contributors may be used to endorse or promote
34 products derived from this software without specific prior
35 written permission.
36
37 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
38 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
40 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
41 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 */
49
50 #define HAVE_MSGHDR_MSG_CONTROL
51 #include "lsapilib.h"
52
53 #include <stdio.h>
54
55 #if HAVE_STDLIB_H
56 #include <stdlib.h>
57 #endif
58
59 #if HAVE_UNISTD_H
60 #include <unistd.h>
61 #endif
62
63 #include <sys/wait.h>
64
65
66 #include <sys/stat.h>
67
68 #if HAVE_SYS_TYPES_H
69
70 #include <sys/types.h>
71
72 #endif
73
74 #include <sys/types.h>
75 #include <sys/socket.h>
76 #include <sys/un.h>
77 #include <arpa/inet.h>
78 #include <netinet/in.h>
79 #include <semaphore.h>
80 #include <sys/mman.h>
81 #include <fcntl.h>
82 #include <dlfcn.h>
83 #include <stdlib.h>
84 #include <errno.h>
85 #include <string.h>
86 #include <stdarg.h>
87
88 #include <signal.h>
89 #include <time.h>
90 #include <sys/timeb.h>
91 #include <unistd.h>
92 #include "lscriu.h"
93
94 #define LSCRIU_PATH 256
95
96 // Begin CRIU inclusion
97 //CRIU inclusion
98 static int s_initial_start_reqs = 0;
99 static int s_requests_count = 0;
100 static int s_restored = 0;
101 static int (*s_lscapi_dump_me)() = NULL;
102 static int (*s_lscapi_prepare_me)() = NULL;
103 static int s_native = 0;
104 static int s_tried_checkpoint = 0;
105 static int s_criu_debug = 0;
106 static int s_fd_native = -1;
107 static char *s_criu_image_path = NULL;
108 static int s_pid = 0;
109
110 typedef enum
111 {
112 CRIU_GCOUNTER_SHM,
113 CRIU_GCOUNTER_SIG,
114 CRIU_GCOUNTER_PIPE
115 } GlobalCounterType_t;
116 static GlobalCounterType_t s_global_counter_type = CRIU_GCOUNTER_SHM;
117
118 #ifndef sighandler_t
119 typedef void (*sighandler_t)(int);
120 #endif
121
122 void lsapi_perror( const char * pMessage, int err_no );
123 void LSAPI_reset_server_state( void );
124 int LSAPI_Get_ppid();
125
126 #ifdef LSAPILIB_DEBUG_CRIU
127 #define lscriu_dbg(...) \
128 do { if (s_criu_debug) fprintf(stderr, __VA_ARGS__); } while(0)
129 #else
130 #define lscriu_dbg(...)
131 #endif
132
133 #define lscriu_err(...) fprintf(stderr, __VA_ARGS__)
134
135
136 #define SUN_PATH_MAX (sizeof(((struct sockaddr_un *)NULL)->sun_path))
137
138 typedef struct
139 {
140 pid_t m_iPidToDump;
141 char m_chImageDirectory[1024];
142 char m_chSocketDir[SUN_PATH_MAX];
143 char m_chServiceAddress[SUN_PATH_MAX];
144 } criu_native_dump_t;
145
146 typedef struct
147 {
148 int m_iDumpResult;
149 char m_chDumpResponseMessage[1024];
150 } criu_native_dump_response_t;
151
152 typedef sem_t * (*psem_open_t) (const char *__name, int __oflag, ...);
153 typedef int (*psem_post_t) (sem_t *__sem);
154 typedef int (*psem_close_t) (sem_t *__sem);
155
156 psem_open_t psem_open = NULL;
157 psem_post_t psem_post = NULL;
158 psem_close_t psem_close = NULL;
159
lsapi_criu_signal(int signo,sighandler_t handler)160 static void lsapi_criu_signal(int signo, sighandler_t handler)
161 {
162 struct sigaction sa;
163
164 sigaction(signo, NULL, &sa);
165
166 if (sa.sa_handler == SIG_DFL) {
167 sigemptyset(&sa.sa_mask);
168 sa.sa_flags = 0;
169 sa.sa_handler = handler;
170 sigaction(signo, &sa, NULL);
171 }
172 }
173
174
lsapi_siguser2(int sig)175 static void lsapi_siguser2(int sig)
176 {
177 // child requests counter for master process
178 ++s_requests_count;
179 }
180
181
LSCRIU_Set_Initial_Start_Reqs(int reqs)182 static void LSCRIU_Set_Initial_Start_Reqs(int reqs)
183 {
184 s_initial_start_reqs = reqs;
185 }
186
187
LSCRIU_Set_Global_Counter_Type(GlobalCounterType_t tp)188 static void LSCRIU_Set_Global_Counter_Type(GlobalCounterType_t tp)
189 {
190 if ((tp == CRIU_GCOUNTER_SHM) || (tp == CRIU_GCOUNTER_SIG)
191 || (tp == CRIU_GCOUNTER_PIPE)) {
192 s_global_counter_type = tp;
193 } else {
194 s_global_counter_type = CRIU_GCOUNTER_SHM;
195 }
196
197 }
198
199
LSCRIU_Get_Global_Counter_Type(void)200 static int LSCRIU_Get_Global_Counter_Type(void)
201 {
202 return s_global_counter_type;
203 }
204
205
LSCRIU_Init_Global_Counter(int value)206 static int LSCRIU_Init_Global_Counter(int value)
207 {
208 if (LSCRIU_Get_Global_Counter_Type() != CRIU_GCOUNTER_SHM
209 || !s_initial_start_reqs) {
210 return 0;
211 }
212
213 return 0;
214 }
215
216
LSCRIU_Increase_Global_Counter(void)217 static void LSCRIU_Increase_Global_Counter(void)
218 {
219 if (LSCRIU_Get_Global_Counter_Type() != CRIU_GCOUNTER_SHM
220 || !s_initial_start_reqs) {
221 return;
222 }
223
224 s_requests_count = LSAPI_Inc_Req_Processed(1);
225 }
226
227
LSCRIU_Get_Global_Counter(void)228 static void LSCRIU_Get_Global_Counter(void)
229 {
230 if (!s_initial_start_reqs) {
231 return;
232 }
233 s_requests_count = LSAPI_Inc_Req_Processed(0);
234
235 }
236
237
LSCRIU_need_checkpoint(void)238 static int LSCRIU_need_checkpoint(void)
239 {
240 if (!s_initial_start_reqs) {
241 return 0;
242 }
243
244 if (LSCRIU_Get_Global_Counter_Type() == CRIU_GCOUNTER_SHM
245 && s_requests_count <= s_initial_start_reqs) {
246 LSCRIU_Get_Global_Counter();
247 }
248 if (s_initial_start_reqs > 0
249 && s_requests_count >= s_initial_start_reqs) {
250 return 1;
251 }
252
253 return 0;
254 }
255
256
LSCRIU_load_liblscapi(void)257 static int LSCRIU_load_liblscapi(void)
258 {
259 void *lib_handle = NULL;
260 void *pthread_lib_handle = NULL;
261
262 if (s_native)
263 return 0;
264 // Numerical signals indicates Apache
265 int error = 1;
266 char *last;
267
268 if (!(lib_handle = dlopen(last = "liblscapi.so", RTLD_LAZY)) /*||
269 !(pthread_lib_handle = dlopen(last = "libpthread.so", RTLD_LAZY))*/)
270 fprintf(stderr, "LSCRIU (%d): failed to dlopen %s: %s - ignore CRIU\n",
271 s_pid, last, dlerror());
272 else if (!(s_lscapi_dump_me = dlsym(lib_handle, last = "lscapi_dump_me")) ||
273 !(s_lscapi_prepare_me = dlsym(lib_handle, last = "lscapi_prepare_me")) ||
274 !(psem_open = dlsym(pthread_lib_handle, last = "sem_open")) ||
275 !(psem_post = dlsym(pthread_lib_handle, last = "sem_post")) ||
276 !(psem_close = dlsym(pthread_lib_handle, last = "sem_close")))
277 fprintf(stderr, "LSCRIU (%d): failed to dlsym %s: %s - ignore CRIU\n",
278 s_pid, last, dlerror());
279 else
280 error = 0;
281 if (error) {
282 // close the dll handles so we release the resources
283 if (lib_handle)
284 dlclose(lib_handle);
285 if (pthread_lib_handle)
286 dlclose(pthread_lib_handle);
287 return -1;
288 }
289 return 0;
290 }
291
292
LSCRIU_Wink_Server_is_Ready(void)293 static void LSCRIU_Wink_Server_is_Ready(void)
294 {
295 char sem_name[60];
296
297 if (s_native) {
298 // Not used for native
299 return;
300 }
301 if (getenv("LSAPI_UNIQE"))
302 snprintf(sem_name, sizeof sem_name - 1, "lsphp[hash=%s].is_ready",
303 getenv("LSAPI_UNIQE"));
304 else
305 snprintf(sem_name, sizeof sem_name - 1, "lsphp[euid=0x%x].is_ready",
306 geteuid());
307
308 sem_t *is_ready_sem = psem_open(sem_name, O_RDWR);
309 if (is_ready_sem) {
310 if (psem_post(is_ready_sem) < 0)
311 lsapi_perror(sem_name, errno);
312
313 if (psem_close(is_ready_sem) < 0)
314 lsapi_perror(sem_name, errno);
315 }
316 else if (errno != ENOENT)
317 lsapi_perror(sem_name, errno);
318 }
319
320
LSCRIU_Error_File_Name(char * pchFile,int max_len)321 static char *LSCRIU_Error_File_Name(char *pchFile, int max_len)
322 {
323 const char *pchDefaultSocketPath = "/tmp/";
324 const char *pchDefaultLogFileName = "lsws_error.log";
325 snprintf(pchFile, max_len, "%s%s", pchDefaultSocketPath,
326 pchDefaultLogFileName);
327 return pchFile;
328 }
329
330
331 #ifdef LSAPILIB_DEBUG_CRIU
LSCRIU_Debugging(void)332 static void LSCRIU_Debugging(void) {
333 char *pchCRIUDebug;
334 pchCRIUDebug = getenv("LSAPI_CRIU_DEBUG");
335 if (!pchCRIUDebug)
336 pchCRIUDebug = getenv("LSCAPI_CRIU_DEBUG");
337 //fprintf(stderr,"(%d) LSCRIU: CRIU debug environment variable: %s\n",
338 // s_pid, pchCRIUDebug);
339 // I've made it easy to turn on debugging. CloudLinux Apache sets
340 // LSCAPI_CRIU_DEBUG to nothing to indicate it's on. Sigh.
341 if ((!pchCRIUDebug) ||
342 ((!*pchCRIUDebug) ||
343 (*pchCRIUDebug == '0') ||
344 (*pchCRIUDebug == 'f') ||
345 (*pchCRIUDebug == 'F') ||
346 (((*pchCRIUDebug == 'O') ||
347 (*pchCRIUDebug == 'o')) &&
348 ((*(pchCRIUDebug + 1)) &&
349 ((*(pchCRIUDebug + 1) == 'F') || (*(pchCRIUDebug + 1) == 'f'))))))
350 {
351 lscriu_dbg("LSCRIU (%d): CRIU Debugging disabled by environment\n", s_pid);
352 s_criu_debug = 0;
353 }
354 else {
355 s_criu_debug = 1;
356 lscriu_dbg("LSCRIU (%d): CRIU Debugging enabled by environment\n", s_pid);
357 fprintf(stderr,"LSCRIU (%d): CRIU debug environment variable: %s\n",
358 s_pid, pchCRIUDebug);
359 }
360 }
361
362
LSCRIU_Restored_Error(int iFatal,char * format,...)363 static void LSCRIU_Restored_Error(int iFatal, char *format, ...) {
364 // This routine deals with the awful situation of trying to get info while the stderr handle is closed on purpose.
365 int iOldUMask;
366 int iFd = -1;
367 char chFile[1024];
368
369 if (!iFatal) {
370 // LSCRIU_Debugging();
371 if (!s_criu_debug) {
372 // Debugging message and debugging is off
373 return;
374 }
375 }
376 if (!LSCRIU_Error_File_Name(chFile, sizeof(chFile))) {
377 // We're done here...nowhere to write
378 return;
379 }
380 iOldUMask = umask(0);
381 iFd = open( chFile, O_WRONLY | O_APPEND | O_CREAT,
382 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
383 umask(iOldUMask);
384 if (iFd >= 0) {
385 char chFullMessage[0x1000];
386 struct timeb sTimeb;
387 struct tm sTm;
388 ftime(&sTimeb);
389 localtime_r(&sTimeb.time,&sTm);
390 va_list ap;
391 va_start(ap, format);
392 char buf[0x1000];
393 vsnprintf(buf, sizeof(buf), format, ap);
394 va_end(ap);
395
396 int n = snprintf(chFullMessage, sizeof(chFullMessage),
397 "%04d-%02d-%02d %02d:%02d:%02d.%03d: LSCRIU (%d): %s %s\n",
398 sTm.tm_year + 1900,
399 sTm.tm_mon + 1,
400 sTm.tm_mday,
401 sTm.tm_hour,
402 sTm.tm_min,
403 sTm.tm_sec,
404 sTimeb.millitm,
405 s_pid,
406 iFatal ? "FATAL! " : "(debug) ",
407 buf);
408 if (n > (int)sizeof(chFullMessage))
409 n = sizeof(chFullMessage);
410 write(iFd, chFullMessage, n);
411 close(iFd);
412 }
413 }
414 #else // no debugging
LSCRIU_Debugging(void)415 static void inline LSCRIU_Debugging(void) {}
LSCRIU_Restored_Error(int iFatal,char * format,...)416 static void inline LSCRIU_Restored_Error(int iFatal, char *format, ...) {}
417 #endif
418
419
LSCRIU_Native_Dump(pid_t iPid,char * pchImagePath,int iFdNative)420 static int LSCRIU_Native_Dump(pid_t iPid,
421 char *pchImagePath,
422 int iFdNative) {
423 criu_native_dump_t criu_native_dump;
424 char *pchLastSlash;
425 criu_native_dump_response_t criu_native_dump_response;
426
427 memset(&criu_native_dump, 0, sizeof(criu_native_dump));
428 criu_native_dump.m_iPidToDump = iPid;
429 strncpy(criu_native_dump.m_chImageDirectory, pchImagePath,
430 sizeof(criu_native_dump.m_chImageDirectory));
431 pchLastSlash = strrchr(criu_native_dump.m_chSocketDir,'/');
432 if (pchLastSlash) {
433 pchLastSlash++;
434 (*pchLastSlash) = 0;
435 }
436 lscriu_dbg("LSCRIU (%d): Sent the dump request to the listener\n", s_pid);
437 if (write(iFdNative,
438 &criu_native_dump,
439 sizeof(criu_native_dump)) == -1) {
440 lscriu_err("LSCRIU (%d): Error sending dump request to the listener: %s\n",
441 s_pid, strerror(errno));
442 return(-1);
443 }
444 return 0;
445 /* do not wait response.
446 //while (sleep(7200));
447 if (read(iFdNative,
448 &criu_native_dump_response,
449 sizeof(criu_native_dump_response)) == -1) {
450 // The test will actually fail it!
451 //LSCRIU_Restored_Error(1, "Error reading dump socket #%d from parent: %s",
452 // iFdNative, strerror(errno));
453 //return(-1);
454 }
455 return(-1);
456 */
457 }
458
459
LSCRIU_CloudLinux_Checkpoint(void)460 static void LSCRIU_CloudLinux_Checkpoint(void)
461 {
462 int iRet;
463
464 if ((!s_native) && (!s_lscapi_dump_me)) {
465 lscriu_dbg("LSCRIU (%d): Not native and unable to dump - abandon one-time "
466 "dump\n", s_pid);
467 return;
468 }
469
470 iRet = s_lscapi_dump_me();
471 if (iRet < 0) {
472 lscriu_err("LSCRIU: CloudLinux dump of PID: %d, error: %s\n",
473 s_pid, strerror(errno));
474 }
475 if (iRet == 0) {
476 // Dumped. To continue the child must send us the handles back
477 lscriu_err("LSCRIU: Successful CloudLinux dump of PID: %d\n", s_pid);
478 }
479 else {
480 s_restored = 1;
481 LSAPI_reset_server_state();
482 /*
483 Here we have restored the php process, so we should to tell (via
484 semaphore) mod_lsapi that we are started and ready to receive data.
485 */
486 LSCRIU_Wink_Server_is_Ready();
487 lscriu_err("LSCRIU: Successful CloudLinux restore of PID: %d, parent: %d.\n",
488 getpid(), getppid());
489 }
490 LSCRIU_Set_Initial_Start_Reqs(0);
491 }
492
493
LSCRIU_Wait_Dump_Finsh_Or_Restored(int pid_parent)494 static void LSCRIU_Wait_Dump_Finsh_Or_Restored(int pid_parent)
495 {
496 // Now get restored. We know if we're restored if the ppid changes!
497 // If we're dumped, we're killed (no use worrying about that!).
498 time_t iTimeStart = 0;
499 time_t iTimeNow;
500 int iRestored = 0;
501 do {
502 usleep(1000);
503 time(&iTimeNow);
504 if (!iTimeStart) {
505 iTimeStart = iTimeNow;
506 }
507 else if ((pid_parent != getppid()) ||
508 (iTimeNow - iTimeStart > 10)) {
509 iRestored = 1;
510 }
511 else if (iTimeNow - iTimeStart > 5) {
512 LSCRIU_Restored_Error(1, "Timed out waiting to be dumped");
513 exit(1);
514 }
515 } while (!iRestored);
516 }
517
518
LSCRIU_try_checkpoint(int * forked_pid)519 static void LSCRIU_try_checkpoint(int *forked_pid)
520 {
521 int iRet;
522 pid_t iPid;
523 pid_t iPidDump = getpid();
524
525 if (s_tried_checkpoint) {
526 lscriu_dbg("LSCRIU (%d): Already tried checkpoint - one time per customer\n",
527 iPidDump);
528 return;
529 }
530 lscriu_dbg("LSCRIU (%d): Trying checkpoint\n", iPidDump);
531 s_tried_checkpoint = 1;
532 if (!s_native) {
533 LSCRIU_CloudLinux_Checkpoint();
534 return;
535 }
536
537 lscriu_dbg("LSCRIU (%d): fork!\n", iPidDump);
538 iPid = fork();
539 if (iPid < 0) {
540 lscriu_err("LSCRIU (%d): Can't checkpoint due to a fork error: %s\n",
541 iPidDump, strerror(errno));
542 return;
543 }
544 if (iPid == 0) {
545 pid_t iPidParent = getppid();
546
547 setsid();
548 iRet = LSCRIU_Native_Dump(iPidDump,
549 s_criu_image_path,
550 s_fd_native);
551 close(s_fd_native);
552
553 LSCRIU_Wait_Dump_Finsh_Or_Restored(iPidParent);
554 LSCRIU_Restored_Error(0, "Restored!");
555 LSAPI_reset_server_state();
556 s_restored = 1;
557 }
558 else {
559 if (forked_pid)
560 *forked_pid = iPid;
561 }
562 LSCRIU_Set_Initial_Start_Reqs(0);
563 }
564
565
init_native_env()566 static int init_native_env()
567 {
568 char *pchFd;
569 pchFd = getenv("LSAPI_CRIU_SYNC_FD");
570 if (!pchFd)
571 pchFd = getenv("LSCAPI_CRIU_SYNC_FD");
572
573 const char *image_path;
574 image_path = getenv("LSAPI_CRIU_IMAGE_PATH");
575 if (!pchFd) {
576 lscriu_err("LSCRIU (%d): LSAPI_CRIU_SYNC_FD internal environment "
577 "variable not set - contact Litespeed tech support\n", getpid());
578 return -1;
579 }
580 if (!image_path) {
581 lscriu_err("LSCRIU (%d): LSAPI_CRIU_IMAGE_PATH internal environment "
582 "variable not set - contact Litespeed tech support\n", getpid());
583 return -1;
584 }
585 lscriu_dbg("LSCRIU (%d): Checkpoint dump. ImagePath: %s\n",
586 getpid(), image_path);
587
588 s_fd_native = atoi(pchFd);
589 lscriu_dbg("LSCRIU (%d): Native checkpoint. Use filepointer %d (%s) to send "
590 "pid %d\n", getpid(), s_fd_native, pchFd, iPidDump);
591 s_criu_image_path = strdup(image_path);
592 return 0;
593 }
594
LSCRIU_Init_Env_Parameters(void)595 static int LSCRIU_Init_Env_Parameters(void)
596 {
597 const char *p;
598 int n;
599
600 p = getenv("LSAPI_INITIAL_START");
601 if (!p)
602 p = getenv("LSAPI_BACKEND_INITIAL_START");
603 if (p) {
604 n = atoi(p);
605
606 if (n > 0) {
607 lscriu_dbg("LSCRIU (%d): Set start requests based on environment (%d)\n",
608 getpid(), n);
609 LSCRIU_Set_Initial_Start_Reqs(n);
610 } else {
611 lscriu_dbg("LSCRIU (%d): LSAPI_INITIAL_START set to 0 disabled\n",
612 getpid());
613 return 0;
614 }
615 } else {
616 lscriu_dbg("LSCRIU (%d): LSAPI_INITIAL_START NOT set - disabled\n",
617 getpid());
618 return 0;
619 }
620 if (LSAPI_Is_Listen()) {
621 lscriu_dbg("LSCRIU (%d): Listening...\n", getpid());
622 GlobalCounterType_t gc_type = CRIU_GCOUNTER_SHM;
623 char *env;
624 if ((env = getenv("LSAPI_CRIU_USE_SHM"))) {
625 // CloudLinux doc: Off (shared memory) or Signals.
626 // Litespeed doc: On (shared memory) or Signals
627 // So just check the first character for an 'S' and if not, then
628 // use shared memory. Pipe support is lost (sigh).
629 if ((*env == 'S') || (*env == 's'))
630 gc_type = CRIU_GCOUNTER_SIG; // Just assume the rest is signals
631 // else use the default of shared memory
632 }
633 else if ((env = getenv("LSAPI_SIGNALS"))) {
634 if ((*env == '1') ||
635 (*env == 'Y') ||
636 (*env == 'y') ||
637 (*env == 'T') ||
638 (*env == 't') ||
639 (((*env == 'O') || (*env == 'o')) &&
640 ((*(env + 1) == 'N') || (*(env + 1) == 'n'))))
641 gc_type = CRIU_GCOUNTER_SIG;
642 else if (*env == 2)
643 gc_type = CRIU_GCOUNTER_PIPE; // The only case for pipe
644 //else use the default of shared memory
645 }
646 if (gc_type != CRIU_GCOUNTER_SHM) {
647 lscriu_dbg("LSCRIU (%d): Use %s\n", getpid(),
648 gc_type == CRIU_GCOUNTER_SIG ? "signals" : "pipe");
649 lsapi_criu_signal(SIGUSR2, lsapi_siguser2);
650 }
651 else
652 lscriu_dbg("LSCRIU (%d): Use shared memory\n", getpid());
653 LSCRIU_Set_Global_Counter_Type(gc_type);
654 }
655 else
656 lscriu_dbg("LSCRIU (%d): NOT Listening\n", getpid());
657
658 char *criu_mode = NULL;
659 criu_mode = getenv("LSAPI_CRIU");
660 // 0 disabled
661 // 1 cloudlinux
662 // 2 native
663 if (criu_mode) {
664 if (*criu_mode == '0') {
665 lscriu_dbg("LSCRIU (%d): Disabled by environment.\n", getpid());
666 LSCRIU_Set_Initial_Start_Reqs(0);
667 }
668 else if (*criu_mode == '2') {
669 lscriu_dbg("LSCRIU (%d): Disabled by environment.\n", getpid());
670 s_native = 1;
671 }
672 }
673
674 if (s_native && init_native_env() == -1)
675 LSCRIU_Set_Initial_Start_Reqs(0);
676
677 //unset_lsapi_envs();
678 return 0;
679 }
680
681
LSCRIU_inc_req_procssed()682 void LSCRIU_inc_req_procssed()
683 {
684 if (!LSCRIU_Get_Global_Counter_Type()) {
685 ++s_requests_count;
686 }
687
688 lscriu_dbg("LSCRIU (%d): s_requests_count %d counter %d\n", getpid(),
689 s_requests_count, s_initial_start_reqs);
690
691 if (s_initial_start_reqs > 0 && s_requests_count <= s_initial_start_reqs) {
692 if (LSCRIU_Get_Global_Counter_Type() == CRIU_GCOUNTER_SHM) {
693 LSCRIU_Increase_Global_Counter();
694 if (s_requests_count >= s_initial_start_reqs) {
695 //Maybe this time we can stop to send signal and wait for
696 //1 second of select timeout
697 //kill( LSCRIU_Get_ppid(), SIGUSR2 );
698 lscriu_dbg("LSCRIU (%d): Time to dump main process with semaphore\n",
699 getpid());
700 }
701 } else {
702 kill(LSAPI_Get_ppid(), SIGUSR2);
703 lscriu_dbg("LSCRIU (%d): Send kill to main process with signals\n",
704 getpid());
705 }
706 }
707 }
708
709
LSCRIU_on_timer(int * forked_pid)710 static void LSCRIU_on_timer(int *forked_pid)
711 {
712 lscriu_dbg("LSCRIU (%d): LSCRIU_on_timer\n", getpid());
713 if (LSCRIU_need_checkpoint()) {
714 LSCRIU_try_checkpoint(forked_pid);
715 }
716 }
717
718
LSCRIU_Init(void)719 int LSCRIU_Init(void)
720 {
721 s_pid = getpid();
722 LSCRIU_Debugging();
723 LSCRIU_Init_Env_Parameters();
724 if (s_initial_start_reqs && !s_native) {
725 if (LSCRIU_load_liblscapi() == -1)
726 s_initial_start_reqs = 0;
727 }
728 if (s_initial_start_reqs) {
729 LSCRIU_Wink_Server_is_Ready();
730 lscriu_dbg("LSCRIU (%d): LSAPI_Register_Pgrp_Timer_Callback\n", s_pid);
731 LSAPI_Register_Pgrp_Timer_Callback(LSCRIU_on_timer);
732 LSCRIU_Init_Global_Counter(0);
733 }
734 return s_initial_start_reqs > 0;
735 }
736