void LSCRIU_inc_req_procssed() { if (!LSCRIU_Get_Global_Counter_Type()) { ++s_requests_count; } lscriu_dbg("LSCRIU (%d): s_requests_count %d counter %d\n", getpid(), s_requests_count, s_initial_start_reqs); if (s_initial_start_reqs > 0 && s_requests_count <= s_initial_start_reqs) { if (LSCRIU_Get_Global_Counter_Type() == CRIU_GCOUNTER_SHM) { LSCRIU_Increase_Global_Counter(); if (s_requests_count >= s_initial_start_reqs) { //Maybe this time we can stop to send signal and wait for //1 second of select timeout //kill( LSCRIU_Get_ppid(), SIGUSR2 ); lscriu_dbg("LSCRIU (%d): Time to dump main process with semaphore\n", getpid()); } } else { kill(LSAPI_Get_ppid(), SIGUSR2); lscriu_dbg("LSCRIU (%d): Send kill to main process with signals\n", getpid()); } } }
static int init_native_env() { char *pchFd; pchFd = getenv("LSAPI_CRIU_SYNC_FD"); if (!pchFd) pchFd = getenv("LSCAPI_CRIU_SYNC_FD"); const char *image_path; image_path = getenv("LSAPI_CRIU_IMAGE_PATH"); if (!pchFd) { lscriu_err("LSCRIU (%d): LSAPI_CRIU_SYNC_FD internal environment " "variable not set - contact Litespeed tech support\n", getpid()); return -1; } if (!image_path) { lscriu_err("LSCRIU (%d): LSAPI_CRIU_IMAGE_PATH internal environment " "variable not set - contact Litespeed tech support\n", getpid()); return -1; } lscriu_dbg("LSCRIU (%d): Checkpoint dump. ImagePath: %s\n", getpid(), image_path); s_fd_native = atoi(pchFd); lscriu_dbg("LSCRIU (%d): Native checkpoint. Use filepointer %d (%s) to send " "pid %d\n", getpid(), s_fd_native, pchFd, iPidDump); s_criu_image_path = strdup(image_path); return 0; }
static void LSCRIU_Debugging(void) { char *pchCRIUDebug; pchCRIUDebug = getenv("LSAPI_CRIU_DEBUG"); if (!pchCRIUDebug) pchCRIUDebug = getenv("LSCAPI_CRIU_DEBUG"); //fprintf(stderr,"(%d) LSCRIU: CRIU debug environment variable: %s\n", // s_pid, pchCRIUDebug); // I've made it easy to turn on debugging. CloudLinux Apache sets // LSCAPI_CRIU_DEBUG to nothing to indicate it's on. Sigh. if ((!pchCRIUDebug) || ((!*pchCRIUDebug) || (*pchCRIUDebug == '0') || (*pchCRIUDebug == 'f') || (*pchCRIUDebug == 'F') || (((*pchCRIUDebug == 'O') || (*pchCRIUDebug == 'o')) && ((*(pchCRIUDebug + 1)) && ((*(pchCRIUDebug + 1) == 'F') || (*(pchCRIUDebug + 1) == 'f')))))) { lscriu_dbg("LSCRIU (%d): CRIU Debugging disabled by environment\n", s_pid); s_criu_debug = 0; } else { s_criu_debug = 1; lscriu_dbg("LSCRIU (%d): CRIU Debugging enabled by environment\n", s_pid); fprintf(stderr,"LSCRIU (%d): CRIU debug environment variable: %s\n", s_pid, pchCRIUDebug); } }
static void LSCRIU_try_checkpoint(int *forked_pid) { int iRet; pid_t iPid; pid_t iPidDump = getpid(); if (s_tried_checkpoint) { lscriu_dbg("LSCRIU (%d): Already tried checkpoint - one time per customer\n", getpid()); return; } lscriu_dbg("LSCRIU (%d): Trying checkpoint\n", getpid()); s_tried_checkpoint = 1; if (!s_native) { LSCRIU_CloudLinux_Checkpoint(); return; } lscriu_dbg("LSCRIU (%d): fork!\n", getpid()); iPid = fork(); if (iPid < 0) { lscriu_err("LSCRIU (%d): Can't checkpoint due to a fork error: %s\n", getpid(), strerror(errno)); return; } if (iPid == 0) { int iResult; pid_t iPidSender; pid_t iPidParent = getppid(); s_pid = getpid(); setsid(); iRet = LSCRIU_Native_Dump(s_pid, s_criu_image_path, s_fd_native); close(s_fd_native); LSCRIU_Wait_Dump_Finsh_Or_Restored(iPidParent); LSCRIU_Restored_Error(0, "Restored!"); LSAPI_reset_server_state(); s_restored = 1; } else { if (forked_pid) *forked_pid = iPid; } LSCRIU_Set_Initial_Start_Reqs(0); }
static void LSCRIU_on_timer(int *forked_pid) { lscriu_dbg("LSCRIU (%d): LSCRIU_on_timer\n", getpid()); if (LSCRIU_need_checkpoint()) { LSCRIU_try_checkpoint(forked_pid); } }
static void LSCRIU_CloudLinux_Checkpoint(void) { int iRet; if ((!s_native) && (!s_lscapi_dump_me)) { lscriu_dbg("LSCRIU (%d): Not native and unable to dump - abandon one-time " "dump\n", s_pid); return; } iRet = s_lscapi_dump_me(); if (iRet < 0) { char *pchError; lscriu_err("LSCRIU: CloudLinux dump of PID: %d, error: %s\n", s_pid, strerror(errno)); } if (iRet == 0) { // Dumped. To continue the child must send us the handles back lscriu_err("LSCRIU: Successful CloudLinux dump of PID: %d\n", s_pid); } else { s_restored = 1; LSAPI_reset_server_state(); /* Here we have restored the php process, so we should to tell (via semaphore) mod_lsapi that we are started and ready to receive data. */ LSCRIU_Wink_Server_is_Ready(); lscriu_err("LSCRIU: Successful CloudLinux restore of PID: %d, parent: %d.\n", getpid(), getppid()); } LSCRIU_Set_Initial_Start_Reqs(0); }
static int LSCRIU_Native_Dump(pid_t iPid, char *pchImagePath, int iFdNative) { criu_native_dump_t criu_native_dump; char *pchLastSlash; memset(&criu_native_dump, 0, sizeof(criu_native_dump)); criu_native_dump.m_iPidToDump = iPid; strncpy(criu_native_dump.m_chImageDirectory, pchImagePath, sizeof(criu_native_dump.m_chImageDirectory)); pchLastSlash = strrchr(criu_native_dump.m_chSocketDir,'/'); if (pchLastSlash) { pchLastSlash++; (*pchLastSlash) = 0; } lscriu_dbg("LSCRIU (%d): Sent the dump request to the listener\n", s_pid); if (write(iFdNative, &criu_native_dump, sizeof(criu_native_dump)) == -1) { lscriu_err("LSCRIU (%d): Error sending dump request to the listener: %s\n", s_pid, strerror(errno)); return(-1); } return 0; }
int LSCRIU_Init(void) { s_pid = getpid(); LSCRIU_Debugging(); LSCRIU_Init_Env_Parameters(); if (s_initial_start_reqs && !s_native) { if (LSCRIU_load_liblscapi() == -1) s_initial_start_reqs = 0; } if (s_initial_start_reqs) { LSCRIU_Wink_Server_is_Ready(); lscriu_dbg("LSCRIU (%d): LSAPI_Register_Pgrp_Timer_Callback\n", s_pid); LSAPI_Register_Pgrp_Timer_Callback(LSCRIU_on_timer); LSCRIU_Init_Global_Counter(0); } return s_initial_start_reqs > 0; }
static int LSCRIU_Native_Dump(pid_t iPid, char *pchImagePath, int iFdNative) { criu_native_dump_t criu_native_dump; char *pchLastSlash; criu_native_dump_response_t criu_native_dump_response; memset(&criu_native_dump, 0, sizeof(criu_native_dump)); criu_native_dump.m_iPidToDump = iPid; strncpy(criu_native_dump.m_chImageDirectory, pchImagePath, sizeof(criu_native_dump.m_chImageDirectory)); pchLastSlash = strrchr(criu_native_dump.m_chSocketDir,'/'); if (pchLastSlash) { pchLastSlash++; (*pchLastSlash) = 0; } lscriu_dbg("LSCRIU (%d): Sent the dump request to the listener\n", s_pid); if (write(iFdNative, &criu_native_dump, sizeof(criu_native_dump)) == -1) { lscriu_err("LSCRIU (%d): Error sending dump request to the listener: %s\n", s_pid, strerror(errno)); return(-1); } return 0; /* do not wait response. //while (sleep(7200)); if (read(iFdNative, &criu_native_dump_response, sizeof(criu_native_dump_response)) == -1) { // The test will actually fail it! //LSCRIU_Restored_Error(1, "Error reading dump socket #%d from parent: %s", // iFdNative, strerror(errno)); //return(-1); } return(-1); */ }
static int LSCRIU_Init_Env_Parameters(void) { const char *p; int n; p = getenv("LSAPI_INITIAL_START"); if (!p) p = getenv("LSAPI_BACKEND_INITIAL_START"); if (p) { n = atoi(p); if (n > 0) { lscriu_dbg("LSCRIU (%d): Set start requests based on environment (%d)\n", getpid(), n); LSCRIU_Set_Initial_Start_Reqs(n); } else { lscriu_dbg("LSCRIU (%d): LSAPI_INITIAL_START set to 0 disabled\n", getpid()); return 0; } } else { lscriu_dbg("LSCRIU (%d): LSAPI_INITIAL_START NOT set - disabled\n", getpid()); return 0; } if (LSAPI_Is_Listen()) { lscriu_dbg("LSCRIU (%d): Listening...\n", getpid()); GlobalCounterType_t gc_type = CRIU_GCOUNTER_SHM; char *env; if ((env = getenv("LSAPI_CRIU_USE_SHM"))) { // CloudLinux doc: Off (shared memory) or Signals. // Litespeed doc: On (shared memory) or Signals // So just check the first character for an 'S' and if not, then // use shared memory. Pipe support is lost (sigh). if ((*env == 'S') || (*env == 's')) gc_type = CRIU_GCOUNTER_SIG; // Just assume the rest is signals // else use the default of shared memory } else if ((env = getenv("LSAPI_SIGNALS"))) { if ((*env == '1') || (*env == 'Y') || (*env == 'y') || (*env == 'T') || (*env == 't') || (((*env == 'O') || (*env == 'o')) && ((*(env + 1) == 'N') || (*(env + 1) == 'n')))) gc_type = CRIU_GCOUNTER_SIG; else if (*env == 2) gc_type = CRIU_GCOUNTER_PIPE; // The only case for pipe //else use the default of shared memory } if (gc_type != CRIU_GCOUNTER_SHM) { lscriu_dbg("LSCRIU (%d): Use %s\n", getpid(), gc_type == CRIU_GCOUNTER_SIG ? "signals" : "pipe"); lsapi_criu_signal(SIGUSR2, lsapi_siguser2); } else lscriu_dbg("LSCRIU (%d): Use shared memory\n", getpid()); LSCRIU_Set_Global_Counter_Type(gc_type); } else lscriu_dbg("LSCRIU (%d): NOT Listening\n", getpid()); char *criu_mode = NULL; char ch; criu_mode = getenv("LSAPI_CRIU"); // 0 disabled // 1 cloudlinux // 2 native if (criu_mode) { if (*criu_mode == '0') { lscriu_dbg("LSCRIU (%d): Disabled by environment.\n", getpid()); LSCRIU_Set_Initial_Start_Reqs(0); } else if (*criu_mode == '2') { lscriu_dbg("LSCRIU (%d): Disabled by environment.\n", getpid()); s_native = 1; } } if (s_native && init_native_env() == -1) LSCRIU_Set_Initial_Start_Reqs(0); //unset_lsapi_envs(); return 0; }