php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
lscriu.c
Go to the documentation of this file.
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/*
17Copyright (c) 2002-2018, Lite Speed Technologies Inc.
18All rights reserved.
19
20Redistribution and use in source and binary forms, with or without
21modification, are permitted provided that the following conditions are
22met:
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
35THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45OF 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#ifdef HAVE_UNISTD_H
55#include <unistd.h>
56#endif
57
58#include <sys/wait.h>
59
60
61#include <sys/stat.h>
62
63#ifdef HAVE_SYS_TYPES_H
64#include <sys/types.h>
65#endif
66
67#include <sys/types.h>
68#include <sys/socket.h>
69#include <sys/un.h>
70#include <arpa/inet.h>
71#include <netinet/in.h>
72#include <semaphore.h>
73#include <sys/mman.h>
74#include <fcntl.h>
75#include <dlfcn.h>
76#include <stdlib.h>
77#include <errno.h>
78#include <string.h>
79#include <stdarg.h>
80
81#include <signal.h>
82#include <time.h>
83#include <sys/timeb.h>
84#include <unistd.h>
85#include "lscriu.h"
86
88
89#define LSCRIU_PATH 256
90
91// Begin CRIU inclusion
92//CRIU inclusion
93static int s_initial_start_reqs = 0;
94static int s_requests_count = 0;
95static int s_restored = 0;
96static int (*s_lscapi_dump_me)(void) = NULL;
97static int (*s_lscapi_prepare_me)(void) = NULL;
98static int s_native = 0;
99static int s_tried_checkpoint = 0;
100#ifdef LSAPILIB_DEBUG_CRIU
101static int s_criu_debug = 0;
102#endif
103static int s_fd_native = -1;
104static char *s_criu_image_path = NULL;
105static int s_pid = 0;
106
113static GlobalCounterType_t s_global_counter_type = CRIU_GCOUNTER_SHM;
114
115#ifndef sighandler_t
116typedef void (*sighandler_t)(int);
117#endif
118
119void lsapi_perror( const char * pMessage, int err_no );
120void LSAPI_reset_server_state( void );
121int LSAPI_Get_ppid(void);
122
123#ifdef LSAPILIB_DEBUG_CRIU
124#define lscriu_dbg(...) \
125 do { if (s_criu_debug) fprintf(stderr, __VA_ARGS__); } while(0)
126#else
127#define lscriu_dbg(...)
128#endif
129
130#define lscriu_err(...) fprintf(stderr, __VA_ARGS__)
131
132
133#define SUN_PATH_MAX (sizeof(((struct sockaddr_un *)NULL)->sun_path))
134
142
143typedef sem_t * (*psem_open_t) (const char *__name, int __oflag, ...);
144typedef int (*psem_post_t) (sem_t *__sem);
145typedef int (*psem_close_t) (sem_t *__sem);
146
150
151static void lsapi_criu_signal(int signo, sighandler_t handler)
152{
153 struct sigaction sa;
154
155 sigaction(signo, NULL, &sa);
156
157 if (sa.sa_handler == SIG_DFL) {
158 sigemptyset(&sa.sa_mask);
159 sa.sa_flags = 0;
160 sa.sa_handler = handler;
161 sigaction(signo, &sa, NULL);
162 }
163}
164
165
166static void lsapi_siguser2(int sig)
167{
168 // child requests counter for master process
169 ++s_requests_count;
170}
171
172
173static void LSCRIU_Set_Initial_Start_Reqs(int reqs)
174{
175 s_initial_start_reqs = reqs;
176}
177
178
179static void LSCRIU_Set_Global_Counter_Type(GlobalCounterType_t tp)
180{
181 if ((tp == CRIU_GCOUNTER_SHM) || (tp == CRIU_GCOUNTER_SIG)
182 || (tp == CRIU_GCOUNTER_PIPE)) {
183 s_global_counter_type = tp;
184 } else {
185 s_global_counter_type = CRIU_GCOUNTER_SHM;
186 }
187
188}
189
190
191static int LSCRIU_Get_Global_Counter_Type(void)
192{
193 return s_global_counter_type;
194}
195
196
197static int LSCRIU_Init_Global_Counter(int value)
198{
199 if (LSCRIU_Get_Global_Counter_Type() != CRIU_GCOUNTER_SHM
200 || !s_initial_start_reqs) {
201 return 0;
202 }
203
204 return 0;
205}
206
207
208static void LSCRIU_Increase_Global_Counter(void)
209{
210 if (LSCRIU_Get_Global_Counter_Type() != CRIU_GCOUNTER_SHM
211 || !s_initial_start_reqs) {
212 return;
213 }
214
215 s_requests_count = LSAPI_Inc_Req_Processed(1);
216}
217
218
219static void LSCRIU_Get_Global_Counter(void)
220{
221 if (!s_initial_start_reqs) {
222 return;
223 }
224 s_requests_count = LSAPI_Inc_Req_Processed(0);
225
226}
227
228
229static int LSCRIU_need_checkpoint(void)
230{
231 if (!s_initial_start_reqs) {
232 return 0;
233 }
234
235 if (LSCRIU_Get_Global_Counter_Type() == CRIU_GCOUNTER_SHM
236 && s_requests_count <= s_initial_start_reqs) {
237 LSCRIU_Get_Global_Counter();
238 }
239 if (s_initial_start_reqs > 0
240 && s_requests_count >= s_initial_start_reqs) {
241 return 1;
242 }
243
244 return 0;
245}
246
247
248static int LSCRIU_load_liblscapi(void)
249{
250 void *lib_handle = NULL;
251 void *pthread_lib_handle = NULL;
252
253 if (s_native)
254 return 0;
255 // Numerical signals indicates Apache
256 int error = 1;
257 char *last;
258
259 if (!(lib_handle = DL_LOAD(last = "liblscapi.so")) /*||
260 !(pthread_lib_handle = DL_LOAD(last = "libpthread.so"))*/)
261 fprintf(stderr, "LSCRIU (%d): failed to dlopen %s: %s - ignore CRIU\n",
262 s_pid, last, dlerror());
263 else if (!(s_lscapi_dump_me = dlsym(lib_handle, last = "lscapi_dump_me")) ||
264 !(s_lscapi_prepare_me = dlsym(lib_handle, last = "lscapi_prepare_me")) ||
265 !(psem_open = dlsym(pthread_lib_handle, last = "sem_open")) ||
266 !(psem_post = dlsym(pthread_lib_handle, last = "sem_post")) ||
267 !(psem_close = dlsym(pthread_lib_handle, last = "sem_close")))
268 fprintf(stderr, "LSCRIU (%d): failed to dlsym %s: %s - ignore CRIU\n",
269 s_pid, last, dlerror());
270 else
271 error = 0;
272 if (error) {
273 // close the dll handles so we release the resources
274 if (lib_handle)
275 dlclose(lib_handle);
276 if (pthread_lib_handle)
277 dlclose(pthread_lib_handle);
278 return -1;
279 }
280 return 0;
281}
282
283
284static void LSCRIU_Wink_Server_is_Ready(void)
285{
286 char sem_name[60];
287
288 if (s_native) {
289 // Not used for native
290 return;
291 }
292 if (getenv("LSAPI_UNIQE"))
293 snprintf(sem_name, sizeof sem_name - 1, "lsphp[hash=%s].is_ready",
294 getenv("LSAPI_UNIQE"));
295 else
296 snprintf(sem_name, sizeof sem_name - 1, "lsphp[euid=0x%x].is_ready",
297 geteuid());
298
299 sem_t *is_ready_sem = psem_open(sem_name, O_RDWR);
300 if (is_ready_sem) {
301 if (psem_post(is_ready_sem) < 0)
302 lsapi_perror(sem_name, errno);
303
304 if (psem_close(is_ready_sem) < 0)
305 lsapi_perror(sem_name, errno);
306 }
307 else if (errno != ENOENT)
308 lsapi_perror(sem_name, errno);
309}
310
311
312#ifdef LSAPILIB_DEBUG_CRIU
313static char *LSCRIU_Error_File_Name(char *pchFile, int max_len)
314{
315 const char *pchDefaultSocketPath = "/tmp/";
316 const char *pchDefaultLogFileName = "lsws_error.log";
317 snprintf(pchFile, max_len, "%s%s", pchDefaultSocketPath,
318 pchDefaultLogFileName);
319 return pchFile;
320}
321
322
323static void LSCRIU_Debugging(void) {
324 char *pchCRIUDebug;
325 pchCRIUDebug = getenv("LSAPI_CRIU_DEBUG");
326 if (!pchCRIUDebug)
327 pchCRIUDebug = getenv("LSCAPI_CRIU_DEBUG");
328 //fprintf(stderr,"(%d) LSCRIU: CRIU debug environment variable: %s\n",
329 // s_pid, pchCRIUDebug);
330 // I've made it easy to turn on debugging. CloudLinux Apache sets
331 // LSCAPI_CRIU_DEBUG to nothing to indicate it's on. Sigh.
332 if ((!pchCRIUDebug) ||
333 ((!*pchCRIUDebug) ||
334 (*pchCRIUDebug == '0') ||
335 (*pchCRIUDebug == 'f') ||
336 (*pchCRIUDebug == 'F') ||
337 (((*pchCRIUDebug == 'O') ||
338 (*pchCRIUDebug == 'o')) &&
339 ((*(pchCRIUDebug + 1)) &&
340 ((*(pchCRIUDebug + 1) == 'F') || (*(pchCRIUDebug + 1) == 'f'))))))
341 {
342 lscriu_dbg("LSCRIU (%d): CRIU Debugging disabled by environment\n", s_pid);
343 s_criu_debug = 0;
344 }
345 else {
346 s_criu_debug = 1;
347 lscriu_dbg("LSCRIU (%d): CRIU Debugging enabled by environment\n", s_pid);
348 fprintf(stderr,"LSCRIU (%d): CRIU debug environment variable: %s\n",
349 s_pid, pchCRIUDebug);
350 }
351}
352
353
354static void LSCRIU_Restored_Error(int iFatal, char *format, ...) {
355 // This routine deals with the awful situation of trying to get info while the stderr handle is closed on purpose.
356 int iOldUMask;
357 int iFd = -1;
358 char chFile[1024];
359
360 if (!iFatal) {
361 // LSCRIU_Debugging();
362 if (!s_criu_debug) {
363 // Debugging message and debugging is off
364 return;
365 }
366 }
367 if (!LSCRIU_Error_File_Name(chFile, sizeof(chFile))) {
368 // We're done here...nowhere to write
369 return;
370 }
371 iOldUMask = umask(0);
372 iFd = open( chFile, O_WRONLY | O_APPEND | O_CREAT,
373 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
374 umask(iOldUMask);
375 if (iFd >= 0) {
376 char chFullMessage[0x1000];
377 struct timeb sTimeb;
378 struct tm sTm;
379 ftime(&sTimeb);
380 localtime_r(&sTimeb.time,&sTm);
381 va_list ap;
382 va_start(ap, format);
383 char buf[0x1000];
384 vsnprintf(buf, sizeof(buf), format, ap);
385 va_end(ap);
386
387 int n = snprintf(chFullMessage, sizeof(chFullMessage),
388 "%04d-%02d-%02d %02d:%02d:%02d.%03d: LSCRIU (%d): %s %s\n",
389 sTm.tm_year + 1900,
390 sTm.tm_mon + 1,
391 sTm.tm_mday,
392 sTm.tm_hour,
393 sTm.tm_min,
394 sTm.tm_sec,
395 sTimeb.millitm,
396 s_pid,
397 iFatal ? "FATAL! " : "(debug) ",
398 buf);
399 if (n > (int)sizeof(chFullMessage))
400 n = sizeof(chFullMessage);
401 write(iFd, chFullMessage, n);
402 close(iFd);
403 }
404}
405#else // no debugging
406static inline void LSCRIU_Debugging(void) {}
407static inline void LSCRIU_Restored_Error(int iFatal, char *format, ...) {}
408#endif
409
410
411static int LSCRIU_Native_Dump(pid_t iPid,
412 char *pchImagePath,
413 int iFdNative) {
414 criu_native_dump_t criu_native_dump;
415 char *pchLastSlash;
416
417 memset(&criu_native_dump, 0, sizeof(criu_native_dump));
418 criu_native_dump.m_iPidToDump = iPid;
419 strncpy(criu_native_dump.m_chImageDirectory, pchImagePath,
420 sizeof(criu_native_dump.m_chImageDirectory) - 1);
421 criu_native_dump.m_chImageDirectory[
422 sizeof(criu_native_dump.m_chImageDirectory) - 1] = '\0';
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
440static 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;
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
474static 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
499static 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!");
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
545static 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
574static 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());
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
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
691static 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
700int 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}
umask(?int $mask=null)
usleep(int $microseconds)
fprintf($stream, string $format, mixed ... $values)
getenv(?string $name=null, bool $local_only=false)
strrchr(string $haystack, string $needle, bool $before_needle=false)
error($message)
Definition ext_skel.php:22
zend_long n
Definition ffi.c:4979
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
#define NULL
Definition gdcache.h:45
int LSAPI_Is_Listen(void)
Definition lsapilib.c:1520
void(* sighandler_t)(int)
Definition lsapilib.c:336
int LSAPI_Inc_Req_Processed(int cnt)
Definition lsapilib.c:4360
void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb)
Definition lsapilib.c:1475
int LSAPI_Get_ppid(void)
Definition lsapilib.c:3800
psem_close_t psem_close
Definition lscriu.c:149
void LSCRIU_inc_req_processed()
Definition lscriu.c:663
GlobalCounterType_t
Definition lscriu.c:108
@ CRIU_GCOUNTER_PIPE
Definition lscriu.c:111
@ CRIU_GCOUNTER_SIG
Definition lscriu.c:110
@ CRIU_GCOUNTER_SHM
Definition lscriu.c:109
sem_t *(* psem_open_t)(const char *__name, int __oflag,...)
Definition lscriu.c:143
int(* psem_close_t)(sem_t *__sem)
Definition lscriu.c:145
psem_open_t psem_open
Definition lscriu.c:147
int(* psem_post_t)(sem_t *__sem)
Definition lscriu.c:144
void LSAPI_reset_server_state(void)
Definition lsapilib.c:2874
#define SUN_PATH_MAX
Definition lscriu.c:133
int LSCRIU_Init(void)
Definition lscriu.c:700
psem_post_t psem_post
Definition lscriu.c:148
#define lscriu_err(...)
Definition lscriu.c:130
void lsapi_perror(const char *pMessage, int err_no)
Definition lsapilib.c:299
#define lscriu_dbg(...)
Definition lscriu.c:127
const SIG_DFL
const SIGUSR2
time()
p
Definition session.c:1105
#define vsnprintf
Definition snprintf.h:104
char m_chImageDirectory[1024]
Definition lscriu.c:138
char m_chServiceAddress[SUN_PATH_MAX]
Definition lscriu.c:140
char m_chSocketDir[SUN_PATH_MAX]
Definition lscriu.c:139
#define close(a)
#define errno
exit(string|int $status=0)
#define snprintf
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
int last
fbc internal_function handler(call, ret)
value