/* Initialize the module internal functions. * * The function reproduces the initialization performed by PostgreSQL * to be able to call the functions in pg_status.c * * Return 0 in case of success, else -1. In case of failure with an error that * shouldn't be ignored, also set a Python exception. * * The function should be called only once in the process lifetime. * so is called at module initialization. After the function is called, * set_ps_display() can be used. */ int spt_setup(void) { int rv = -1; #ifndef WIN32 int argc = 0; char **argv = NULL; char *init_title; if (0 > get_argc_argv(&argc, &argv)) { spt_debug("get_argc_argv failed"); goto exit; } save_ps_display_args(argc, argv); /* Set up the first title to fully initialize the code */ if (!(init_title = join_argv(argc, argv))) { goto exit; } init_ps_display(init_title); free(init_title); #else /* On Windows save_ps_display_args is a no-op * This is a good news, because Py_GetArgcArgv seems not usable. */ LPTSTR init_title = GetCommandLine(); init_ps_display(init_title); #endif rv = 0; exit: return rv; }
/* Initialize the module internal functions. * * The function reproduces the initialization performed by PostgreSQL * to be able to call the functions in pg_status.c * * The function should be called only once in the process lifetime. * so is called at module initialization. After the function is called, * set_ps_display() can be used. */ void spt_setup(void) { #ifndef WIN32 int argc = 0; char **argv = NULL; if (!get_argc_argv(&argc, &argv)) { spt_debug("setup failed"); goto exit; } save_ps_display_args(argc, argv); /* Set up the first title to fully initialize the code */ char *init_title = join_argv(argc, argv); init_ps_display(init_title); free(init_title); #else /* On Windows save_ps_display_args is a no-op * This is a good news, because Py_GetArgcArgv seems not usable. */ LPTSTR init_title = GetCommandLine(); init_ps_display(init_title); #endif exit: /* clear the exception. Propagating it to the module init would make a * fatal error. What we want instead is just to create a no-op module. */ PyErr_Clear(); }
/* * fork a child for PCP */ pid_t pcp_fork_a_child(int unix_fd, int inet_fd, char *pcp_conf_file) { pid_t pid; pid = fork(); if (pid == 0) { close(pipe_fds[0]); close(pipe_fds[1]); myargv = save_ps_display_args(myargc, myargv); /* call PCP child main */ POOL_SETMASK(&UnBlockSig); reload_config_request = 0; pcp_do_child(unix_fd, inet_fd, pcp_conf_file); } else if (pid == -1) { pool_error("fork() failed. reason: %s", strerror(errno)); myexit(1); } return pid; }
/* Initialize the module internal functions. * * The function reproduces the initialization performed by PostgreSQL * to be able to call the functions in pg_status.c * * The function should be called only once in the process lifetime. * so is called at module initialization. After the function is called, * set_ps_display() can be used. */ void spt_setup(void) { #ifndef WIN32 int argc = 0; char **argv = NULL; if (!get_argc_argv(&argc, &argv)) { spt_debug("setup failed"); return; } save_ps_display_args(argc, argv); /* Set up the first title to fully initialize the code */ char *init_title = join_argv(argc, argv); init_ps_display(init_title); free(init_title); #else /* On Windows save_ps_display_args is a no-op * This is a good news, because Py_GetArgcArgv seems not usable. */ LPTSTR init_title = GetCommandLine(); init_ps_display(init_title); #endif }
/* fork lifecheck process*/ static pid_t fork_a_lifecheck(int fork_wait_time) { pid_t pid; pid = fork(); if (pid != 0) { if (pid == -1) pool_error("fork_a_lifecheck: fork() failed."); return pid; } if (fork_wait_time > 0) { sleep(fork_wait_time); } myargv = save_ps_display_args(myargc, myargv); POOL_SETMASK(&UnBlockSig); init_ps_display("", "", "", ""); signal(SIGTERM, wd_exit); signal(SIGINT, wd_exit); signal(SIGQUIT, wd_exit); signal(SIGCHLD, SIG_DFL); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); set_ps_display("lifecheck",false); /* wait until ready to go */ while (WD_OK != is_wd_lifecheck_ready()) { sleep(pool_config->wd_interval * 10); } pool_log("watchdog: lifecheck started"); /* watchdog loop */ for (;;) { /* pgpool life check */ wd_lifecheck(); sleep(pool_config->wd_interval); } return pid; }
void initsetproctitle(void) { PyObject *m, *d; /* Create the module and add the functions */ m = Py_InitModule3("setproctitle", spt_methods, setproctitle_module_documentation); /* Add version string to the module*/ d = PyModule_GetDict(m); spt_version = PyString_FromString(xstr(SPT_VERSION)); PyDict_SetItemString(d, "__version__", spt_version); /* Initialize the process title */ #ifndef WIN32 int argc; char **argv; Py_GetArgcArgv(&argc, &argv); argv = fix_argv(argc, argv); save_ps_display_args(argc, argv); /* Set up the first title to fully initialize the code */ char *init_title = join_argv(argc, argv); init_ps_display(init_title); free(init_title); #else /* On Windows save_ps_display_args is a no-op * This is a good news, because Py_GetArgcArgv seems not usable. */ LPTSTR init_title = GetCommandLine(); init_ps_display(init_title); #endif /* Check for errors */ if (PyErr_Occurred()) Py_FatalError("can't initialize module setproctitle"); }
/* * fork a child */ pid_t fork_a_child(int unix_fd, int inet_fd, int id) { pid_t pid; pid = fork(); if (pid == 0) { /* Before we unconditionally closed pipe_fds[0] and pipe_fds[1] * here, which is apparently wrong since in the start up of * pgpool, pipe(2) is not called yet and it mistakenly closes * fd 0. Now we check the fd > 0 before close(), expecting * pipe returns fds greater than 0. Note that we cannot * unconditionally remove close(2) calls since fork_a_child() * may be called *after* pgpool starting up. */ if (pipe_fds[0] > 0) { close(pipe_fds[0]); close(pipe_fds[1]); } myargv = save_ps_display_args(myargc, myargv); /* call child main */ POOL_SETMASK(&UnBlockSig); reload_config_request = 0; my_proc_id = id; do_child(unix_fd, inet_fd); } else if (pid == -1) { pool_error("fork() failed. reason: %s", strerror(errno)); myexit(1); } return pid; }
/* * Any Postgres server process begins execution here. */ int main(int argc, char *argv[]) { progname = get_progname(argv[0]); /* * Platform-specific startup hacks */ startup_hacks(progname); /* * Remember the physical location of the initially given argv[] array for * possible use by ps display. On some platforms, the argv[] storage must * be overwritten in order to set the process title for ps. In such cases * save_ps_display_args makes and returns a new copy of the argv[] array. * * save_ps_display_args may also move the environment strings to make * extra room. Therefore this should be done as early as possible during * startup, to avoid entanglements with code that might save a getenv() * result pointer. */ argv = save_ps_display_args(argc, argv); /* * If supported on the current platform, set up a handler to be called if * the backend/postmaster crashes with a fatal signal or exception. */ #if defined(WIN32) && defined(HAVE_MINIDUMP_TYPE) pgwin32_install_crashdump_handler(); #endif /* * Set up locale information from environment. Note that LC_CTYPE and * LC_COLLATE will be overridden later from pg_control if we are in an * already-initialized database. We set them here so that they will be * available to fill pg_control during initdb. LC_MESSAGES will get set * later during GUC option processing, but we set it here to allow startup * error messages to be localized. */ set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("postgres")); #ifdef WIN32 /* * Windows uses codepages rather than the environment, so we work around * that by querying the environment explicitly first for LC_COLLATE and * LC_CTYPE. We have to do this because initdb passes those values in the * environment. If there is nothing there we fall back on the codepage. */ { char *env_locale; if ((env_locale = getenv("LC_COLLATE")) != NULL) pg_perm_setlocale(LC_COLLATE, env_locale); else pg_perm_setlocale(LC_COLLATE, ""); if ((env_locale = getenv("LC_CTYPE")) != NULL) pg_perm_setlocale(LC_CTYPE, env_locale); else pg_perm_setlocale(LC_CTYPE, ""); } #else pg_perm_setlocale(LC_COLLATE, ""); pg_perm_setlocale(LC_CTYPE, ""); #endif #ifdef LC_MESSAGES pg_perm_setlocale(LC_MESSAGES, ""); #endif /* * We keep these set to "C" always, except transiently in pg_locale.c; see * that file for explanations. */ pg_perm_setlocale(LC_MONETARY, "C"); pg_perm_setlocale(LC_NUMERIC, "C"); pg_perm_setlocale(LC_TIME, "C"); /* * Now that we have absorbed as much as we wish to from the locale * environment, remove any LC_ALL setting, so that the environment * variables installed by pg_perm_setlocale have force. */ unsetenv("LC_ALL"); /* * Catch standard options before doing much else */ if (argc > 1) { if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) { help(progname); exit(0); } if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) { puts("postgres (PostgreSQL) " PG_VERSION); exit(0); } } /* * Make sure we are not running as root. */ check_root(progname); /* * Dispatch to one of various subprograms depending on first argument. */ #ifdef EXEC_BACKEND if (argc > 1 && strncmp(argv[1], "--fork", 6) == 0) exit(SubPostmasterMain(argc, argv)); #endif #ifdef WIN32 /* * Start our win32 signal implementation * * SubPostmasterMain() will do this for itself, but the remaining modes * need it here */ pgwin32_signal_initialize(); #endif if (argc > 1 && strcmp(argv[1], "--boot") == 0) AuxiliaryProcessMain(argc, argv); /* does not return */ if (argc > 1 && strcmp(argv[1], "--describe-config") == 0) exit(GucInfoMain()); if (argc > 1 && strcmp(argv[1], "--single") == 0) exit(PostgresMain(argc, argv, get_current_username(progname))); exit(PostmasterMain(argc, argv)); }
pid_t wd_child(int fork_wait_time) { int sock; int fd; int rtn; pid_t pid = 0; pid = fork(); if (pid != 0) { if (pid == -1) pool_error("wd_child: fork() failed."); return pid; } if (fork_wait_time > 0) { sleep(fork_wait_time); } myargv = save_ps_display_args(myargc, myargv); POOL_SETMASK(&UnBlockSig); signal(SIGTERM, wd_child_exit); signal(SIGINT, wd_child_exit); signal(SIGQUIT, wd_child_exit); signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGALRM, SIG_IGN); init_ps_display("", "", "", ""); if (WD_List == NULL) { /* memory allocate is not ready */ wd_child_exit(15); } sock = wd_create_recv_socket(WD_MYSELF->wd_port); if (sock < 0) { /* socket create failed */ wd_child_exit(15); } set_ps_display("watchdog", false); /* child loop */ for(;;) { WdPacket buf; fd = wd_accept(sock); if (fd < 0) { continue; } rtn = wd_recv_packet(fd, &buf); if (rtn == WD_OK) { wd_send_response(fd, &buf); } close(fd); } return pid; }
pid_t wd_hb_sender(int fork_wait_time, WdHbIf hb_if) { int sock; pid_t pid = 0; WdHbPacket pkt; WdInfo * p = WD_List; char pack_str[WD_MAX_PACKET_STRING]; int pack_str_len; pid = fork(); if (pid != 0) { if (pid == -1) pool_error("wd_hb_sender: fork() failed."); return pid; } if (fork_wait_time > 0) { sleep(fork_wait_time); } myargv = save_ps_display_args(myargc, myargv); POOL_SETMASK(&UnBlockSig); signal(SIGTERM, hb_sender_exit); signal(SIGINT, hb_sender_exit); signal(SIGQUIT, hb_sender_exit); signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGALRM, SIG_IGN); init_ps_display("", "", "", ""); if ( (sock = wd_create_hb_send_socket(hb_if)) < 0) { pool_error("wd_hb_sender: socket create failed"); hb_sender_exit(SIGTERM); } set_ps_display("heartbeat sender", false); for(;;) { gettimeofday(&pkt.send_time, NULL); strlcpy(pkt.from, pool_config->wd_hostname, sizeof(pkt.from)); pkt.status = p->status; if (strlen(pool_config->wd_authkey)) { /* calculate hash from packet */ pack_str_len = packet_to_string_hb(pkt, pack_str, sizeof(pack_str)); wd_calc_hash(pack_str, pack_str_len, pkt.hash); } wd_hb_send(sock, &pkt, sizeof(pkt), hb_if.addr); pool_debug("wd_hb_sender: send heartbeat signal to %s", hb_if.addr); sleep(pool_config->wd_heartbeat_keepalive); } return pid; }
pid_t wd_hb_receiver(int fork_wait_time, WdHbIf hb_if) { int sock; pid_t pid = 0; WdHbPacket pkt; struct timeval tv; char from[WD_MAX_HOST_NAMELEN]; char buf[(MD5_PASSWD_LEN+1)*2]; char pack_str[WD_MAX_PACKET_STRING]; int pack_str_len; WdInfo * p; pid = fork(); if (pid != 0) { if (pid == -1) pool_error("wd_hb_receiver: fork() failed."); return pid; } if (fork_wait_time > 0) { sleep(fork_wait_time); } myargv = save_ps_display_args(myargc, myargv); POOL_SETMASK(&UnBlockSig); signal(SIGTERM, hb_receiver_exit); signal(SIGINT, hb_receiver_exit); signal(SIGQUIT, hb_receiver_exit); signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGALRM, SIG_IGN); init_ps_display("", "", "", ""); if ( (sock = wd_create_hb_recv_socket(hb_if)) < 0) { pool_error("wd_hb_receiver: socket create failed"); hb_receiver_exit(SIGTERM); } set_ps_display("heartbeat receiver", false); for(;;) { if (wd_hb_recv(sock, &pkt) == WD_OK) { /* authentication */ if (strlen(pool_config->wd_authkey)) { /* calculate hash from packet */ pack_str_len = packet_to_string_hb(pkt, pack_str, sizeof(pack_str)); wd_calc_hash(pack_str, pack_str_len, buf); if (strcmp(pkt.hash, buf)) { pool_log("wd_hb_receiver: authentication failed"); continue; } } /* get current time */ gettimeofday(&tv, NULL); /* who send this packet? */ strlcpy(from, pkt.from, sizeof(from)); p = WD_List; while (p->status != WD_END) { if (!strcmp(p->hostname, from)) { /* this is the first packet or the latest packet */ if (!WD_TIME_ISSET(p->hb_send_time) || WD_TIME_BEFORE(p->hb_send_time, pkt.send_time)) { pool_debug("wd_hb_receiver: received heartbeat signal from %s", from); p->hb_send_time = pkt.send_time; p->hb_last_recv_time = tv; } break; } p++; } } } return pid; }
/* * Any Postgres server process begins execution here. */ int main(int argc, char *argv[]) { bool do_check_root = true; progname = get_progname(argv[0]); /* * Platform-specific startup hacks */ startup_hacks(progname); /* * Remember the physical location of the initially given argv[] array for * possible use by ps display. On some platforms, the argv[] storage must * be overwritten in order to set the process title for ps. In such cases * save_ps_display_args makes and returns a new copy of the argv[] array. * * save_ps_display_args may also move the environment strings to make * extra room. Therefore this should be done as early as possible during * startup, to avoid entanglements with code that might save a getenv() * result pointer. */ argv = save_ps_display_args(argc, argv); /* * If supported on the current platform, set up a handler to be called if * the backend/postmaster crashes with a fatal signal or exception. */ #if defined(WIN32) && defined(HAVE_MINIDUMP_TYPE) pgwin32_install_crashdump_handler(); #endif /* * Fire up essential subsystems: error and memory management * * Code after this point is allowed to use elog/ereport, though * localization of messages may not work right away, and messages won't go * anywhere but stderr until GUC settings get loaded. */ MemoryContextInit(); /* * Set up locale information from environment. Note that LC_CTYPE and * LC_COLLATE will be overridden later from pg_control if we are in an * already-initialized database. We set them here so that they will be * available to fill pg_control during initdb. LC_MESSAGES will get set * later during GUC option processing, but we set it here to allow startup * error messages to be localized. */ set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("postgres")); #ifdef WIN32 /* * Windows uses codepages rather than the environment, so we work around * that by querying the environment explicitly first for LC_COLLATE and * LC_CTYPE. We have to do this because initdb passes those values in the * environment. If there is nothing there we fall back on the codepage. */ { char *env_locale; if ((env_locale = getenv("LC_COLLATE")) != NULL) init_locale("LC_COLLATE", LC_COLLATE, env_locale); else init_locale("LC_COLLATE", LC_COLLATE, ""); if ((env_locale = getenv("LC_CTYPE")) != NULL) init_locale("LC_CTYPE", LC_CTYPE, env_locale); else init_locale("LC_CTYPE", LC_CTYPE, ""); } #else init_locale("LC_COLLATE", LC_COLLATE, ""); init_locale("LC_CTYPE", LC_CTYPE, ""); #endif #ifdef LC_MESSAGES init_locale("LC_MESSAGES", LC_MESSAGES, ""); #endif /* * We keep these set to "C" always, except transiently in pg_locale.c; see * that file for explanations. */ init_locale("LC_MONETARY", LC_MONETARY, "C"); init_locale("LC_NUMERIC", LC_NUMERIC, "C"); init_locale("LC_TIME", LC_TIME, "C"); /* * Now that we have absorbed as much as we wish to from the locale * environment, remove any LC_ALL setting, so that the environment * variables installed by pg_perm_setlocale have force. */ unsetenv("LC_ALL"); check_strxfrm_bug(); /* * Catch standard options before doing much else, in particular before we * insist on not being root. */ if (argc > 1) { if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) { help(progname); exit(0); } if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) { puts("postgres (PostgreSQL) " PG_VERSION); exit(0); } /* * In addition to the above, we allow "--describe-config" and "-C var" * to be called by root. This is reasonably safe since these are * read-only activities. The -C case is important because pg_ctl may * try to invoke it while still holding administrator privileges on * Windows. Note that while -C can normally be in any argv position, * if you want to bypass the root check you must put it first. This * reduces the risk that we might misinterpret some other mode's -C * switch as being the postmaster/postgres one. */ if (strcmp(argv[1], "--describe-config") == 0) do_check_root = false; else if (argc > 2 && strcmp(argv[1], "-C") == 0) do_check_root = false; } /* * Make sure we are not running as root, unless it's safe for the selected * option. */ if (do_check_root) check_root(progname); /* * Dispatch to one of various subprograms depending on first argument. */ #ifdef EXEC_BACKEND if (argc > 1 && strncmp(argv[1], "--fork", 6) == 0) SubPostmasterMain(argc, argv); /* does not return */ #endif #ifdef WIN32 /* * Start our win32 signal implementation * * SubPostmasterMain() will do this for itself, but the remaining modes * need it here */ pgwin32_signal_initialize(); #endif if (argc > 1 && strcmp(argv[1], "--boot") == 0) AuxiliaryProcessMain(argc, argv); /* does not return */ else if (argc > 1 && strcmp(argv[1], "--describe-config") == 0) GucInfoMain(); /* does not return */ else if (argc > 1 && strcmp(argv[1], "--single") == 0) PostgresMain(argc, argv, NULL, /* no dbname */ strdup(get_user_name_or_exit(progname))); /* does not return */ else PostmasterMain(argc, argv); /* does not return */ abort(); /* should not get here */ }