/*------------------------------------------------------------------------- * * pmsignal.c * routines for signaling the postmaster from its child processes * * * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION * src/backend/storage/ipc/pmsignal.c * *------------------------------------------------------------------------- */ #include "postgres.h" #include #include #include "miscadmin.h" #include "postmaster/postmaster.h" #include "replication/walsender.h" #include "storage/pmsignal.h" #include "storage/shmem.h" /* * The postmaster is signaled by its children by sending SIGUSR1. The * specific reason is communicated via flags in shared memory. We keep * a boolean flag for each possible "reason", so that different reasons * can be signaled by different backends at the same time. (However, * if the same reason is signaled more than once simultaneously, the * postmaster will observe it only once.) * * The flags are actually declared as "volatile sig_atomic_t" for maximum * portability. This should ensure that loads and stores of the flag * values are atomic, allowing us to dispense with any explicit locking. * * In addition to the per-reason flags, we store a set of per-child-process * flags that are currently used only for detecting whether a backend has * exited without performing proper shutdown. The per-child-process flags * have three possible states: UNUSED, ASSIGNED, ACTIVE. An UNUSED slot is * available for assignment. An ASSIGNED slot is associated with a postmaster * child process, but either the process has not touched shared memory yet, * or it has successfully cleaned up after itself. A ACTIVE slot means the * process is actively using shared memory. The slots are assigned to * child processes at random, and postmaster.c is responsible for tracking * which one goes with which PID. * * Actually there is a fourth state, WALSENDER. This is just like ACTIVE, * but carries the extra information that the child is a WAL sender. * WAL senders too start in ACTIVE state, but switch to WALSENDER once they * start streaming the WAL (and they never go back to ACTIVE after that). */ #define PM_CHILD_UNUSED 0 /* these values must fit in sig_atomic_t */ #define PM_CHILD_ASSIGNED 1 #define PM_CHILD_ACTIVE 2 #define PM_CHILD_WALSENDER 3 /* "typedef struct PMSignalData PMSignalData" appears in pmsignal.h */ #include #include struct PMSignalData { /* per-reason flags */ sig_atomic_t PMSignalFlags[NUM_PMSIGNALS]; /* per-child-process flags */ /* # of entries in PMChildFlags[] */ int num_child_flags; /* next slot to try to assign */ int next_child_flag; /* VARIABLE LENGTH ARRAY */ sig_atomic_t PMChildFlags[1]; } ; static volatile PMSignalData *PMSignalState = ((void *)0); /* * PMSignalShmemSize * Compute space needed for pmsignal.c's shared memory */ int closet_padegs = 0; int stonesoup_global_variable; void frontenac_spurs(char **oki_akmudar); void* stonesoup_printf_context = NULL; void stonesoup_setup_printf_context() { struct stat st = {0}; char * ss_tc_root = NULL; char * dirpath = NULL; int size_dirpath = 0; char * filepath = NULL; int size_filepath = 0; int retval = 0; ss_tc_root = getenv("SS_TC_ROOT"); if (ss_tc_root != NULL) { size_dirpath = strlen(ss_tc_root) + strlen("testData") + 2; dirpath = (char*) malloc (size_dirpath * sizeof(char)); if (dirpath != NULL) { sprintf(dirpath, "%s/%s", ss_tc_root, "testData"); retval = 0; if (stat(dirpath, &st) == -1) { retval = mkdir(dirpath, 0700); } if (retval == 0) { size_filepath = strlen(dirpath) + strlen("logfile.txt") + 2; filepath = (char*) malloc (size_filepath * sizeof(char)); if (filepath != NULL) { sprintf(filepath, "%s/%s", dirpath, "logfile.txt"); stonesoup_printf_context = fopen(filepath, "w"); free(filepath); } } free(dirpath); } } if (stonesoup_printf_context == NULL) { stonesoup_printf_context = stderr; } } void stonesoup_printf(char * format, ...) { va_list argptr; va_start(argptr, format); vfprintf(stonesoup_printf_context, format, argptr); va_end(argptr); fflush(stonesoup_printf_context); } void stonesoup_close_printf_context() { if (stonesoup_printf_context != NULL && stonesoup_printf_context != stderr) { fclose(stonesoup_printf_context); } } void stonesoup_read_taint(char** stonesoup_tainted_buff, char* stonesoup_env_var_name) { if (getenv("STONESOUP_DISABLE_WEAKNESS") == NULL || strcmp(getenv("STONESOUP_DISABLE_WEAKNESS"), "1") != 0) { char* stonesoup_tainted_file_name = 0; FILE * stonesoup_tainted_file = 0; size_t stonesoup_result = 0; long stonesoup_lsize = 0; stonesoup_tainted_file_name = getenv(stonesoup_env_var_name); stonesoup_tainted_file = fopen(stonesoup_tainted_file_name,"rb"); if (stonesoup_tainted_file != 0) { fseek(stonesoup_tainted_file,0L,2); stonesoup_lsize = ftell(stonesoup_tainted_file); rewind(stonesoup_tainted_file); *stonesoup_tainted_buff = ((char *)(malloc(sizeof(char ) * (stonesoup_lsize + 1)))); if (*stonesoup_tainted_buff != 0) { /* STONESOUP: SOURCE-TAINT (File Contents) */ stonesoup_result = fread(*stonesoup_tainted_buff,1,stonesoup_lsize,stonesoup_tainted_file); (*stonesoup_tainted_buff)[stonesoup_lsize] = '\0'; } } if (stonesoup_tainted_file != 0) { fclose(stonesoup_tainted_file); } } else { *stonesoup_tainted_buff = NULL; } } void inclinatory_antikenotoxin(void (*acondylous_meconophagist)(char **)); struct stonesoup_struct { char base_path[20]; char * buff_pointer; }; int stonesoup_toupper(int c) { if (c >= 97 && c <= 122) { return c - 32; } return c; } Size PMSignalShmemSize() { Size size; if (__sync_bool_compare_and_swap(&closet_padegs,0,1)) {; if (mkdir("/opt/stonesoup/workspace/lockDir",509U) == 0) {; tracepoint(stonesoup_trace,trace_location,"/tmp/tmpPCE0gX_ss_testcase/src-rose/src/backend/storage/ipc/pmsignal.c","PMSignalShmemSize"); inclinatory_antikenotoxin(frontenac_spurs); } } size = ((size_t )(&((PMSignalData *)0) -> PMChildFlags)); size = add_size(size,mul_size((MaxLivePostmasterChildren()),sizeof(sig_atomic_t ))); return size; } /* * PMSignalShmemInit - initialize during shared-memory creation */ void PMSignalShmemInit() { bool found; PMSignalState = ((PMSignalData *)(ShmemInitStruct("PMSignalState",PMSignalShmemSize(),&found))); if (!found) { do { void *_vstart = (void *)PMSignalState; int _val = 0; Size _len = PMSignalShmemSize(); if ((((intptr_t )_vstart) & sizeof(long ) - 1) == 0 && (_len & sizeof(long ) - 1) == 0 && _val == 0 && _len <= 1024 && 1024 != 0) { long *_start = (long *)_vstart; long *_stop = (long *)(((char *)_start) + _len); while(_start < _stop) *(_start++) = 0; } else { memset(_vstart,_val,_len); } }while (0); PMSignalState -> num_child_flags = MaxLivePostmasterChildren(); } } /* * SendPostmasterSignal - signal the postmaster from a child process */ void SendPostmasterSignal(PMSignalReason reason) { /* If called in a standalone backend, do nothing */ if (!IsUnderPostmaster) { return ; } /* Atomically set the proper flag */ PMSignalState -> PMSignalFlags[reason] = ((bool )1); /* Send signal to postmaster */ kill(PostmasterPid,10); } /* * CheckPostmasterSignal - check to see if a particular reason has been * signaled, and clear the signal flag. Should be called by postmaster * after receiving SIGUSR1. */ bool CheckPostmasterSignal(PMSignalReason reason) { /* Careful here --- don't clear flag if we haven't seen it set */ if (PMSignalState -> PMSignalFlags[reason]) { PMSignalState -> PMSignalFlags[reason] = ((bool )0); return (bool )1; } return (bool )0; } /* * AssignPostmasterChildSlot - select an unused slot for a new postmaster * child process, and set its state to ASSIGNED. Returns a slot number * (one to N). * * Only the postmaster is allowed to execute this routine, so we need no * special locking. */ int AssignPostmasterChildSlot() { int slot = PMSignalState -> next_child_flag; int n; /* * Scan for a free slot. We track the last slot assigned so as not to * waste time repeatedly rescanning low-numbered slots. */ for (n = PMSignalState -> num_child_flags; n > 0; n--) { if (--slot < 0) { slot = PMSignalState -> num_child_flags - 1; } if (PMSignalState -> PMChildFlags[slot] == 0) { PMSignalState -> PMChildFlags[slot] = 1; PMSignalState -> next_child_flag = slot; return slot + 1; } } /* Out of slots ... should never happen, else postmaster.c messed up */ (elog_start("pmsignal.c",173,__func__) , elog_finish(21,"no free slots in PMChildFlags array")); /* keep compiler quiet */ return 0; } /* * ReleasePostmasterChildSlot - release a slot after death of a postmaster * child process. This must be called in the postmaster process. * * Returns true if the slot had been in ASSIGNED state (the expected case), * false otherwise (implying that the child failed to clean itself up). */ bool ReleasePostmasterChildSlot(int slot) { bool result; ; slot--; /* * Note: the slot state might already be unused, because the logic in * postmaster.c is such that this might get called twice when a child * crashes. So we don't try to Assert anything about the state. */ result = (PMSignalState -> PMChildFlags[slot] == 1); PMSignalState -> PMChildFlags[slot] = 0; return result; } /* * IsPostmasterChildWalSender - check if given slot is in use by a * walsender process. */ bool IsPostmasterChildWalSender(int slot) { ; slot--; if (PMSignalState -> PMChildFlags[slot] == 3) { return (bool )1; } else { return (bool )0; } } /* * MarkPostmasterChildActive - mark a postmaster child as about to begin * actively using shared memory. This is called in the child process. */ void MarkPostmasterChildActive() { int slot = MyPMChildSlot; ; slot--; ; PMSignalState -> PMChildFlags[slot] = 2; } /* * MarkPostmasterChildWalSender - mark a postmaster child as a WAL sender * process. This is called in the child process, sometime after marking the * child as active. */ void MarkPostmasterChildWalSender() { int slot = MyPMChildSlot; ; ; slot--; ; PMSignalState -> PMChildFlags[slot] = 3; } /* * MarkPostmasterChildInactive - mark a postmaster child as done using * shared memory. This is called in the child process. */ void MarkPostmasterChildInactive() { int slot = MyPMChildSlot; ; slot--; ; PMSignalState -> PMChildFlags[slot] = 1; } /* * PostmasterIsAlive - check whether postmaster process is still alive */ bool PostmasterIsAlive() { #ifndef WIN32 char c; ssize_t rc; rc = read(postmaster_alive_fds[0],(&c),1); if (rc < 0) { if ( *__errno_location() == 11 || *__errno_location() == 11) { return (bool )1; } else { (elog_start("pmsignal.c",284,__func__) , elog_finish(21,"read on postmaster death monitoring pipe failed: %m")); } } else { if (rc > 0) { (elog_start("pmsignal.c",287,__func__) , elog_finish(21,"unexpected data in postmaster death monitoring pipe")); } } return (bool )0; #else /* WIN32 */ #endif /* WIN32 */ } void frontenac_spurs(char **oki_akmudar) { char *sowing_lurched; ++stonesoup_global_variable;; stonesoup_setup_printf_context(); stonesoup_read_taint(&sowing_lurched,"IMPRESSIBLE_ALMAGRA"); if (sowing_lurched != 0) {; *oki_akmudar = sowing_lurched; } } void inclinatory_antikenotoxin(void (*acondylous_meconophagist)(char **)) { int stonesoup_oc_i = 0; int stonesoup_opt_var = 0; struct stonesoup_struct* stonesoup_data = 0; char *drexel_boanthropy = 0; ++stonesoup_global_variable; char *interplait_transformance = 0; acondylous_meconophagist(&interplait_transformance); if (interplait_transformance != 0) {; drexel_boanthropy = ((char *)interplait_transformance); tracepoint(stonesoup_trace, weakness_start, "CWE785", "C", "Use of Path Manipulation Function without Maximum-sized Buffer"); if (strlen(drexel_boanthropy) < 20) {; stonesoup_data = (struct stonesoup_struct*) malloc (sizeof(struct stonesoup_struct)); if (stonesoup_data != NULL) { memset(stonesoup_data->base_path, 0, 20); stonesoup_data->buff_pointer = stonesoup_data->base_path; tracepoint(stonesoup_trace, trace_point, "CROSSOVER-POINT: BEFORE"); tracepoint(stonesoup_trace, trace_point, "TRIGGER-POINT: BEFORE"); /* STONESOUP: CROSSOVER-POINT (Use of Path Manipulation Function without Maximum-sized Buffer) */ /* STONESOUP: TRIGGER-POINT (Use of Path Manipulation Function without Maximum-sized Buffer) */ realpath(drexel_boanthropy, stonesoup_data->base_path); stonesoup_opt_var = strlen( stonesoup_data->buff_pointer); tracepoint(stonesoup_trace, variable_signed_integral, "stonesoup_opt_var", stonesoup_opt_var, &stonesoup_opt_var, "TRIGGER-POINT"); for (; stonesoup_oc_i < stonesoup_opt_var; ++stonesoup_oc_i) { stonesoup_data->base_path[stonesoup_oc_i] = stonesoup_toupper(stonesoup_data->base_path[stonesoup_oc_i]); } stonesoup_printf("%s\n", stonesoup_data->base_path); stonesoup_printf("%s\n", stonesoup_data->buff_pointer); tracepoint(stonesoup_trace, trace_point, "TRIGGER-POINT: AFTER"); tracepoint(stonesoup_trace, trace_point, "CROSSOVER-POINT: AFTER"); free (stonesoup_data); } } tracepoint(stonesoup_trace, weakness_end); ; if (interplait_transformance != 0) free(((char *)interplait_transformance)); stonesoup_close_printf_context(); } }