void check_mypid() { pid_t pid = 0; if (can_stat(conf.bot->pid_file)) pid = checkpid(conf.bot->nick, NULL); if (pid && (pid != getpid())) fatal(STR("getpid() does not match pid in file. Possible cloned process, exiting.."), 0); }
/** * @brief * Get the pid of the database from the postmaster.pid * file located inside directory pointed by dbstore * * @param[in] dbstore - The path to the database data directory * * @retval 0 - Function failed * @retval >0 - Pid of the postmaster master process * * @par MT-safe: Yes */ static pid_t get_pid() { char pidfile[MAXPATHLEN+1]; FILE *fp; char buf[TEMP_BUF_SIZE+1]; pid_t pid = 0; #ifdef WIN32 snprintf(pidfile, MAXPATHLEN, "%s\\datastore\\postmaster.pid", pbs_conf.pbs_home_path); #else snprintf(pidfile, MAXPATHLEN, "%s/datastore/postmaster.pid", pbs_conf.pbs_home_path); #endif if (access(pidfile, R_OK) != 0) return 0; if ((fp = fopen(pidfile, "r")) == NULL) return 0; memset(buf, 0, TEMP_BUF_SIZE + 1); fgets(buf, TEMP_BUF_SIZE, fp); buf[TEMP_BUF_SIZE] = '\0'; fclose(fp); if (strlen(buf) == 0) return 0; pid = atol(buf); if (pid == 0) return 0; #ifdef WIN32 if (!checkpid(pid)) return 0; #else if (kill(pid, 0) != 0) return 0; #endif return pid; }
/** * @brief * The child part of the monitor functionality on Windows. * * This function is called as a separate executable (child) process * from the parent monitor, and is passed the location of the * data directory. The parent launches this function as a process and waits * to read the stdout of the child process. * @par * This function attempts to lock the lockfile (inside dbstore) and if it * fails, it prints the reason of failure to lock, to its stdout; the child * process also exits in this case. * @par * If the function succeeds in locking the file, it prints "0" to its stdout * resulting in the parent to exit with success to its caller. In that case * this process (child) continues to run in the background, as long as the * monitored database process is still up, holding onto the lock, so that no * other process can lock this file (and thus not be able to start the database). * @par * If and when eventually the database goes down, this function unlocks the file * and quits (allowing others to lock the file and start the database). * * @retval 0 : Function succeeded for the given operation * @retval 1 : Failed (eg to lock the file). * * @par MT-safe: Yes */ int win_db_monitor_child() { HANDLE hFile; BOOL fSuccess = FALSE; pid_t dbpid; int i; char lockfile[MAXPATHLEN + 1]; char reason[RES_BUF_SIZE]; reason[0] = '\0'; /* clear any residual stop db file before starting monitoring */ clear_stop_db_file(); snprintf(lockfile, MAXPATHLEN, "%s\\datastore\\pbs_dblock", pbs_conf.pbs_home_path); hFile = acquire_lock(lockfile, reason, sizeof(reason), NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("%s", reason); fflush(stdout); return 1; } /* set success event */ printf("0"); fflush(stdout); fclose(stdin); fclose(stderr); fclose(stdout); /* dont need stdout after this */ /* * okay, so we locked the file. Now find postgres pid * then loop forever as long as pid is up */ dbpid = 0; for (i = 0; i < MAX_DBPID_ATTEMPTS; i++) { if ((dbpid = get_pid()) > 0) break; sleep(1); } if (dbpid == 0) { lock_out(hFile, F_UNLCK); CloseHandle(hFile); unlink(lockfile); return 0; /* this will unlock the lock in the datastore */ } while (1) { if (!checkpid(dbpid)) break; if (!((dbpid = get_pid()) > 0)) break; /* check if stop db file exists */ check_and_stop_db(dbpid); sleep(1); } /* unlock and return */ lock_out(hFile, F_UNLCK); CloseHandle(hFile); unlink(lockfile); /* clear temporary err files created at startup; windows only case */ clear_tmp_files(); return 0; }