* Create a lockfile. * * filename is the path name of the lockfile to create. * amPostmaster is used to determine how to encode the output PID. * socketDir is the Unix socket directory path to include (possibly empty). * isDDLock and refName are used to determine what error message to produce. */
| 1040 | * isDDLock and refName are used to determine what error message to produce. |
| 1041 | */ |
| 1042 | static void |
| 1043 | CreateLockFile(const char *filename, bool amPostmaster, |
| 1044 | const char *socketDir, |
| 1045 | bool isDDLock, const char *refName) |
| 1046 | { |
| 1047 | int fd; |
| 1048 | char buffer[MAXPGPATH * 2 + 256]; |
| 1049 | int ntries; |
| 1050 | int len; |
| 1051 | int encoded_pid; |
| 1052 | pid_t other_pid; |
| 1053 | pid_t my_pid, |
| 1054 | my_p_pid, |
| 1055 | my_gp_pid; |
| 1056 | const char *envvar; |
| 1057 | |
| 1058 | /* |
| 1059 | * If the PID in the lockfile is our own PID or our parent's or |
| 1060 | * grandparent's PID, then the file must be stale (probably left over from |
| 1061 | * a previous system boot cycle). We need to check this because of the |
| 1062 | * likelihood that a reboot will assign exactly the same PID as we had in |
| 1063 | * the previous reboot, or one that's only one or two counts larger and |
| 1064 | * hence the lockfile's PID now refers to an ancestor shell process. We |
| 1065 | * allow pg_ctl to pass down its parent shell PID (our grandparent PID) |
| 1066 | * via the environment variable PG_GRANDPARENT_PID; this is so that |
| 1067 | * launching the postmaster via pg_ctl can be just as reliable as |
| 1068 | * launching it directly. There is no provision for detecting |
| 1069 | * further-removed ancestor processes, but if the init script is written |
| 1070 | * carefully then all but the immediate parent shell will be root-owned |
| 1071 | * processes and so the kill test will fail with EPERM. Note that we |
| 1072 | * cannot get a false negative this way, because an existing postmaster |
| 1073 | * would surely never launch a competing postmaster or pg_ctl process |
| 1074 | * directly. |
| 1075 | */ |
| 1076 | my_pid = getpid(); |
| 1077 | |
| 1078 | #ifndef WIN32 |
| 1079 | my_p_pid = getppid(); |
| 1080 | #else |
| 1081 | |
| 1082 | /* |
| 1083 | * Windows hasn't got getppid(), but doesn't need it since it's not using |
| 1084 | * real kill() either... |
| 1085 | */ |
| 1086 | my_p_pid = 0; |
| 1087 | #endif |
| 1088 | |
| 1089 | envvar = getenv("PG_GRANDPARENT_PID"); |
| 1090 | if (envvar) |
| 1091 | my_gp_pid = atoi(envvar); |
| 1092 | else |
| 1093 | my_gp_pid = 0; |
| 1094 | |
| 1095 | /* |
| 1096 | * We need a loop here because of race conditions. But don't loop forever |
| 1097 | * (for example, a non-writable $PGDATA directory might cause a failure |
| 1098 | * that won't go away). 100 tries seems like plenty. |
| 1099 | */ |
no test coverage detected