1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 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 #include <stdlib.h>
55
56 #if HAVE_UNISTD_H
57 #include <unistd.h>
58 #endif
59
60 #include <sys/wait.h>
61
62
63 #include <sys/stat.h>
64
65 #if HAVE_SYS_TYPES_H
66
67 #include <sys/types.h>
68
69 #endif
70
71 #include <sys/types.h>
72 #include <sys/socket.h>
73 #include <sys/un.h>
74 #include <arpa/inet.h>
75 #include <netinet/in.h>
76 #include <semaphore.h>
77 #include <sys/mman.h>
78 #include <fcntl.h>
79 #include <dlfcn.h>
80 #include <stdlib.h>
81 #include <errno.h>
82 #include <string.h>
83 #include <stdarg.h>
84
85 #include <signal.h>
86 #include <time.h>
87 #include <sys/timeb.h>
88 #include <unistd.h>
89 #include "lscriu.h"
90
91 #include <Zend/zend_portability.h>
92
93 #define LSCRIU_PATH 256
94
95 // Begin CRIU inclusion
96 //CRIU inclusion
97 static int s_initial_start_reqs = 0;
98 static int s_requests_count = 0;
99 static int s_restored = 0;
100 static int (*s_lscapi_dump_me)() = NULL;
101 static int (*s_lscapi_prepare_me)() = NULL;
102 static int s_native = 0;
103 static int s_tried_checkpoint = 0;
104 static int s_criu_debug = 0;
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();
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
LSCRIU_Error_File_Name(char * pchFile,int max_len)314 static char *LSCRIU_Error_File_Name(char *pchFile, int max_len)
315 {
316 const char *pchDefaultSocketPath = "/tmp/";
317 const char *pchDefaultLogFileName = "lsws_error.log";
318 snprintf(pchFile, max_len, "%s%s", pchDefaultSocketPath,
319 pchDefaultLogFileName);
320 return pchFile;
321 }
322
323
324 #ifdef LSAPILIB_DEBUG_CRIU
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 void inline LSCRIU_Debugging(void) {}
LSCRIU_Restored_Error(int iFatal,char * format,...)409 static void inline 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_Finsh_Or_Restored(int pid_parent)474 static void LSCRIU_Wait_Dump_Finsh_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 int iRet;
502 pid_t iPid;
503 pid_t iPidDump = getpid();
504
505 if (s_tried_checkpoint) {
506 lscriu_dbg("LSCRIU (%d): Already tried checkpoint - one time per customer\n",
507 iPidDump);
508 return;
509 }
510 lscriu_dbg("LSCRIU (%d): Trying checkpoint\n", iPidDump);
511 s_tried_checkpoint = 1;
512 if (!s_native) {
513 LSCRIU_CloudLinux_Checkpoint();
514 return;
515 }
516
517 lscriu_dbg("LSCRIU (%d): fork!\n", iPidDump);
518 iPid = fork();
519 if (iPid < 0) {
520 lscriu_err("LSCRIU (%d): Can't checkpoint due to a fork error: %s\n",
521 iPidDump, strerror(errno));
522 return;
523 }
524 if (iPid == 0) {
525 pid_t iPidParent = getppid();
526
527 setsid();
528 iRet = LSCRIU_Native_Dump(iPidDump,
529 s_criu_image_path,
530 s_fd_native);
531 close(s_fd_native);
532
533 LSCRIU_Wait_Dump_Finsh_Or_Restored(iPidParent);
534 LSCRIU_Restored_Error(0, "Restored!");
535 LSAPI_reset_server_state();
536 s_restored = 1;
537 }
538 else {
539 if (forked_pid)
540 *forked_pid = iPid;
541 }
542 LSCRIU_Set_Initial_Start_Reqs(0);
543 }
544
545
init_native_env()546 static int init_native_env()
547 {
548 char *pchFd;
549 pchFd = getenv("LSAPI_CRIU_SYNC_FD");
550 if (!pchFd)
551 pchFd = getenv("LSCAPI_CRIU_SYNC_FD");
552
553 const char *image_path;
554 image_path = getenv("LSAPI_CRIU_IMAGE_PATH");
555 if (!pchFd) {
556 lscriu_err("LSCRIU (%d): LSAPI_CRIU_SYNC_FD internal environment "
557 "variable not set - contact Litespeed tech support\n", getpid());
558 return -1;
559 }
560 if (!image_path) {
561 lscriu_err("LSCRIU (%d): LSAPI_CRIU_IMAGE_PATH internal environment "
562 "variable not set - contact Litespeed tech support\n", getpid());
563 return -1;
564 }
565 lscriu_dbg("LSCRIU (%d): Checkpoint dump. ImagePath: %s\n",
566 getpid(), image_path);
567
568 s_fd_native = atoi(pchFd);
569 lscriu_dbg("LSCRIU (%d): Native checkpoint. Use filepointer %d (%s) to send "
570 "pid %d\n", getpid(), s_fd_native, pchFd, iPidDump);
571 s_criu_image_path = strdup(image_path);
572 return 0;
573 }
574
LSCRIU_Init_Env_Parameters(void)575 static int LSCRIU_Init_Env_Parameters(void)
576 {
577 const char *p;
578 int n;
579
580 p = getenv("LSAPI_INITIAL_START");
581 if (!p)
582 p = getenv("LSAPI_BACKEND_INITIAL_START");
583 if (p) {
584 n = atoi(p);
585
586 if (n > 0) {
587 lscriu_dbg("LSCRIU (%d): Set start requests based on environment (%d)\n",
588 getpid(), n);
589 LSCRIU_Set_Initial_Start_Reqs(n);
590 } else {
591 lscriu_dbg("LSCRIU (%d): LSAPI_INITIAL_START set to 0 disabled\n",
592 getpid());
593 return 0;
594 }
595 } else {
596 lscriu_dbg("LSCRIU (%d): LSAPI_INITIAL_START NOT set - disabled\n",
597 getpid());
598 return 0;
599 }
600 if (LSAPI_Is_Listen()) {
601 lscriu_dbg("LSCRIU (%d): Listening...\n", getpid());
602 GlobalCounterType_t gc_type = CRIU_GCOUNTER_SHM;
603 char *env;
604 if ((env = getenv("LSAPI_CRIU_USE_SHM"))) {
605 // CloudLinux doc: Off (shared memory) or Signals.
606 // Litespeed doc: On (shared memory) or Signals
607 // So just check the first character for an 'S' and if not, then
608 // use shared memory. Pipe support is lost (sigh).
609 if ((*env == 'S') || (*env == 's'))
610 gc_type = CRIU_GCOUNTER_SIG; // Just assume the rest is signals
611 // else use the default of shared memory
612 }
613 else if ((env = getenv("LSAPI_SIGNALS"))) {
614 if ((*env == '1') ||
615 (*env == 'Y') ||
616 (*env == 'y') ||
617 (*env == 'T') ||
618 (*env == 't') ||
619 (((*env == 'O') || (*env == 'o')) &&
620 ((*(env + 1) == 'N') || (*(env + 1) == 'n'))))
621 gc_type = CRIU_GCOUNTER_SIG;
622 else if (*env == 2)
623 gc_type = CRIU_GCOUNTER_PIPE; // The only case for pipe
624 //else use the default of shared memory
625 }
626 if (gc_type != CRIU_GCOUNTER_SHM) {
627 lscriu_dbg("LSCRIU (%d): Use %s\n", getpid(),
628 gc_type == CRIU_GCOUNTER_SIG ? "signals" : "pipe");
629 lsapi_criu_signal(SIGUSR2, lsapi_siguser2);
630 }
631 else
632 lscriu_dbg("LSCRIU (%d): Use shared memory\n", getpid());
633 LSCRIU_Set_Global_Counter_Type(gc_type);
634 }
635 else
636 lscriu_dbg("LSCRIU (%d): NOT Listening\n", getpid());
637
638 char *criu_mode = NULL;
639 criu_mode = getenv("LSAPI_CRIU");
640 // 0 disabled
641 // 1 cloudlinux
642 // 2 native
643 if (criu_mode) {
644 if (*criu_mode == '0') {
645 lscriu_dbg("LSCRIU (%d): Disabled by environment.\n", getpid());
646 LSCRIU_Set_Initial_Start_Reqs(0);
647 }
648 else if (*criu_mode == '2') {
649 lscriu_dbg("LSCRIU (%d): Disabled by environment.\n", getpid());
650 s_native = 1;
651 }
652 }
653
654 if (s_native && init_native_env() == -1)
655 LSCRIU_Set_Initial_Start_Reqs(0);
656
657 //unset_lsapi_envs();
658 return 0;
659 }
660
661
LSCRIU_inc_req_procssed()662 void LSCRIU_inc_req_procssed()
663 {
664 if (!LSCRIU_Get_Global_Counter_Type()) {
665 ++s_requests_count;
666 }
667
668 lscriu_dbg("LSCRIU (%d): s_requests_count %d counter %d\n", getpid(),
669 s_requests_count, s_initial_start_reqs);
670
671 if (s_initial_start_reqs > 0 && s_requests_count <= s_initial_start_reqs) {
672 if (LSCRIU_Get_Global_Counter_Type() == CRIU_GCOUNTER_SHM) {
673 LSCRIU_Increase_Global_Counter();
674 if (s_requests_count >= s_initial_start_reqs) {
675 //Maybe this time we can stop to send signal and wait for
676 //1 second of select timeout
677 //kill( LSCRIU_Get_ppid(), SIGUSR2 );
678 lscriu_dbg("LSCRIU (%d): Time to dump main process with semaphore\n",
679 getpid());
680 }
681 } else {
682 kill(LSAPI_Get_ppid(), SIGUSR2);
683 lscriu_dbg("LSCRIU (%d): Send kill to main process with signals\n",
684 getpid());
685 }
686 }
687 }
688
689
LSCRIU_on_timer(int * forked_pid)690 static void LSCRIU_on_timer(int *forked_pid)
691 {
692 lscriu_dbg("LSCRIU (%d): LSCRIU_on_timer\n", getpid());
693 if (LSCRIU_need_checkpoint()) {
694 LSCRIU_try_checkpoint(forked_pid);
695 }
696 }
697
698
LSCRIU_Init(void)699 int LSCRIU_Init(void)
700 {
701 s_pid = getpid();
702 LSCRIU_Debugging();
703 LSCRIU_Init_Env_Parameters();
704 if (s_initial_start_reqs && !s_native) {
705 if (LSCRIU_load_liblscapi() == -1)
706 s_initial_start_reqs = 0;
707 }
708 if (s_initial_start_reqs) {
709 LSCRIU_Wink_Server_is_Ready();
710 lscriu_dbg("LSCRIU (%d): LSAPI_Register_Pgrp_Timer_Callback\n", s_pid);
711 LSAPI_Register_Pgrp_Timer_Callback(LSCRIU_on_timer);
712 LSCRIU_Init_Global_Counter(0);
713 }
714 return s_initial_start_reqs > 0;
715 }
716