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