PostgreSQL Source Code: src/backend/postmaster/launch_backend.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
33
35
55
56#ifdef EXEC_BACKEND
60#endif
61
62
63#ifdef EXEC_BACKEND
64
73
74
75#ifdef WIN32
76typedef struct
77{
78 SOCKET origsocket;
79
80 WSAPROTOCOL_INFO wsainfo;
81} InheritableSocket;
82#else
83typedef int InheritableSocket;
84#endif
85
86
87
88
89typedef struct
90{
92#ifndef WIN32
94#else
97#endif
100#ifdef USE_INJECTION_POINTS
101 struct InjectionPointsCtl *ActiveInjectionPoints;
102#endif
122#ifdef WIN32
123 HANDLE PostmasterHandle;
124 HANDLE initial_signal_pipe;
126#else
129#endif
132
134
135
136
137
138
139
140
142 InheritableSocket inh_sock;
143
144
145
146
147 size_t startup_data_len;
149} BackendParameters;
150
151#define SizeOfBackendParameters(startup_data_len) (offsetof(BackendParameters, startup_data) + startup_data_len)
152
153static void read_backend_variables(char *id, void **startup_data, size_t *startup_data_len);
154static void restore_backend_variables(BackendParameters *param);
155
156static bool save_backend_variables(BackendParameters *param, int child_slot,
158#ifdef WIN32
159 HANDLE childProcess, pid_t childPid,
160#endif
161 const void *startup_data, size_t startup_data_len);
162
163static pid_t internal_forkexec(const char *child_kind, int child_slot,
164 const void *startup_data, size_t startup_data_len,
166
167#endif
168
169
170
171
172typedef struct
173{
175 void (*main_fn) (const void *startup_data, size_t startup_data_len);
178
180 [B_INVALID] = {"invalid", NULL, false},
181
187
188
189
190
191
192
195
197
206
208};
209
210const char *
212{
214}
215
216
217
218
219
220
221
222
223
224
225
226
227
228pid_t
230 const void *startup_data, size_t startup_data_len,
232{
233 pid_t pid;
234
236
237
240
241#ifdef EXEC_BACKEND
243 startup_data, startup_data_len, client_sock);
244
245#else
247 if (pid == 0)
248 {
249
251 {
257 }
258
259
261
262
264
265
267 {
270 }
271
272
273
274
275
276
277
279
281 if (client_sock)
282 {
285 }
286
287
288
289
292 }
293#endif
294 return pid;
295}
296
297#ifdef EXEC_BACKEND
298#ifndef WIN32
299
300
301
302
303
304
305
306static pid_t
307internal_forkexec(const char *child_kind, int child_slot,
308 const void *startup_data, size_t startup_data_len, ClientSocket *client_sock)
309{
310 static unsigned long tmpBackendFileNum = 0;
311 pid_t pid;
313 size_t paramsz;
314 BackendParameters *param;
315 FILE *fp;
316 char *argv[4];
318
319
320
321
322
323
324
325
326 paramsz = SizeOfBackendParameters(startup_data_len);
327 param = palloc0(paramsz);
328 if (!save_backend_variables(param, child_slot, client_sock, startup_data, startup_data_len))
329 {
331 return -1;
332 }
333
334
338
339
341 if (!fp)
342 {
343
344
345
346
348
350 if (!fp)
351 {
354 errmsg("could not create file \"%s\": %m",
355 tmpfilename)));
357 return -1;
358 }
359 }
360
361 if (fwrite(param, paramsz, 1, fp) != 1)
362 {
365 errmsg("could not write to file \"%s\": %m", tmpfilename)));
368 return -1;
369 }
371
372
374 {
377 errmsg("could not write to file \"%s\": %m", tmpfilename)));
378 return -1;
379 }
380
381
382 argv[0] = "postgres";
384 argv[1] = forkav;
385
386 argv[2] = tmpfilename;
387 argv[3] = NULL;
388
389
391 {
392 if (execv(postgres_exec_path, argv) < 0)
393 {
395 (errmsg("could not execute server process \"%s\": %m",
396 postgres_exec_path)));
397
398 exit(1);
399 }
400 }
401
402 return pid;
403}
404#else
405
406
407
408
409
410
411
412
413
414
415
416static pid_t
417internal_forkexec(const char *child_kind, int child_slot,
418 const void *startup_data, size_t startup_data_len, ClientSocket *client_sock)
419{
420 int retry_count = 0;
421 STARTUPINFO si;
422 PROCESS_INFORMATION pi;
424 HANDLE paramHandle;
425 BackendParameters *param;
426 SECURITY_ATTRIBUTES sa;
427 size_t paramsz;
428 char paramHandleStr[32];
429 int l;
430
431 paramsz = SizeOfBackendParameters(startup_data_len);
432
433
434retry:
435
436
437 ZeroMemory(&sa, sizeof(sa));
439 sa.bInheritHandle = TRUE;
440 paramHandle = CreateFileMapping(INVALID_HANDLE_VALUE,
442 PAGE_READWRITE,
443 0,
444 paramsz,
445 NULL);
446 if (paramHandle == INVALID_HANDLE_VALUE)
447 {
449 (errmsg("could not create backend parameter file mapping: error code %lu",
450 GetLastError())));
451 return -1;
452 }
453 param = MapViewOfFile(paramHandle, FILE_MAP_WRITE, 0, 0, paramsz);
454 if (!param)
455 {
457 (errmsg("could not map backend parameter memory: error code %lu",
458 GetLastError())));
459 CloseHandle(paramHandle);
460 return -1;
461 }
462
463
464#ifdef _WIN64
465 sprintf(paramHandleStr, "%llu", (LONG_PTR) paramHandle);
466#else
467 sprintf(paramHandleStr, "%lu", (DWORD) paramHandle);
468#endif
469 l = snprintf(cmdLine, sizeof(cmdLine) - 1, "\"%s\" --forkchild=\"%s\" %s",
470 postgres_exec_path, child_kind, paramHandleStr);
471 if (l >= sizeof(cmdLine))
472 {
474 (errmsg("subprocess command line too long")));
475 UnmapViewOfFile(param);
476 CloseHandle(paramHandle);
477 return -1;
478 }
479
480 memset(&pi, 0, sizeof(pi));
481 memset(&si, 0, sizeof(si));
482 si.cb = sizeof(si);
483
484
485
486
487
488 if (!CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, CREATE_SUSPENDED,
489 NULL, NULL, &si, &pi))
490 {
492 (errmsg("CreateProcess() call failed: %m (error code %lu)",
493 GetLastError())));
494 UnmapViewOfFile(param);
495 CloseHandle(paramHandle);
496 return -1;
497 }
498
499 if (!save_backend_variables(param, child_slot, client_sock,
500 pi.hProcess, pi.dwProcessId,
501 startup_data, startup_data_len))
502 {
503
504
505
506
507 if (!TerminateProcess(pi.hProcess, 255))
509 (errmsg_internal("could not terminate unstarted process: error code %lu",
510 GetLastError())));
511 CloseHandle(pi.hProcess);
512 CloseHandle(pi.hThread);
513 UnmapViewOfFile(param);
514 CloseHandle(paramHandle);
515 return -1;
516 }
517
518
519 if (!UnmapViewOfFile(param))
521 (errmsg("could not unmap view of backend parameter file: error code %lu",
522 GetLastError())));
523 if (!CloseHandle(paramHandle))
525 (errmsg("could not close handle to backend parameter file: error code %lu",
526 GetLastError())));
527
528
529
530
531
532
533
534
536 {
537
538 if (!TerminateProcess(pi.hProcess, 255))
540 (errmsg_internal("could not terminate process that failed to reserve memory: error code %lu",
541 GetLastError())));
542 CloseHandle(pi.hProcess);
543 CloseHandle(pi.hThread);
544 if (++retry_count < 100)
545 goto retry;
547 (errmsg("giving up after too many tries to reserve shared memory"),
548 errhint("This might be caused by ASLR or antivirus software.")));
549 return -1;
550 }
551
552
553
554
555
556
557 if (ResumeThread(pi.hThread) == -1)
558 {
559 if (!TerminateProcess(pi.hProcess, 255))
560 {
562 (errmsg_internal("could not terminate unstartable process: error code %lu",
563 GetLastError())));
564 CloseHandle(pi.hProcess);
565 CloseHandle(pi.hThread);
566 return -1;
567 }
568 CloseHandle(pi.hProcess);
569 CloseHandle(pi.hThread);
571 (errmsg_internal("could not resume thread of unstarted process: error code %lu",
572 GetLastError())));
573 return -1;
574 }
575
576
577 pgwin32_register_deadchild_callback(pi.hProcess, pi.dwProcessId);
578
579
580
581 CloseHandle(pi.hThread);
582
583 return pi.dwProcessId;
584}
585#endif
586
587
588
589
590
591
592
593
594
595
596
597void
598SubPostmasterMain(int argc, char *argv[])
599{
600 void *startup_data;
601 size_t startup_data_len;
602 char *child_kind;
604 bool found = false;
606
607
610
611
612
613
614
616
617
619
620
621 if (argc != 3)
622 elog(FATAL, "invalid subpostmaster invocation");
623
624
625 if (strncmp(argv[1], "--forkchild=", 12) != 0)
626 elog(FATAL, "invalid subpostmaster invocation (--forkchild argument missing)");
627 child_kind = argv[1] + 12;
628 found = false;
630 {
632 {
634 found = true;
635 break;
636 }
637 }
638 if (!found)
639 elog(ERROR, "unknown child kind %s", child_kind);
640
641
642 read_backend_variables(argv[2], &startup_data, &startup_data_len);
643
644
646
647
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
668 else
670
671
672 read_nondefault_variables();
673
674
676 {
682 }
683
684
685
686
687
688
689
691
692
693
694
695
697
698
699
700
701
702
703
705
706
709
710
711
712
715}
716
717#ifndef WIN32
718#define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
719#define read_inheritable_socket(dest, src) (*(dest) = *(src))
720#else
721static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
722static bool write_inheritable_socket(InheritableSocket *dest, SOCKET src,
723 pid_t childPid);
724static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
725#endif
726
727
728
729static bool
730save_backend_variables(BackendParameters *param,
732#ifdef WIN32
733 HANDLE childProcess, pid_t childPid,
734#endif
735 const void *startup_data, size_t startup_data_len)
736{
737 if (client_sock)
738 memcpy(¶m->client_sock, client_sock, sizeof(ClientSocket));
739 else
740 memset(¶m->client_sock, 0, sizeof(ClientSocket));
741 if (!write_inheritable_socket(¶m->inh_sock,
743 childPid))
744 return false;
745
747
748 param->MyPMChildSlot = child_slot;
749
750#ifdef WIN32
752#endif
755
757
758#ifdef USE_INJECTION_POINTS
759 param->ActiveInjectionPoints = ActiveInjectionPoints;
760#endif
761
771
776
781
784
785#ifdef WIN32
786 param->PostmasterHandle = PostmasterHandle;
787 if (!write_duplicated_handle(¶m->initial_signal_pipe,
789 childProcess))
790 return false;
791#else
794#endif
795
797
799
801
802 param->startup_data_len = startup_data_len;
803 if (startup_data_len > 0)
804 memcpy(param->startup_data, startup_data, startup_data_len);
805
806 return true;
807}
808
809#ifdef WIN32
810
811
812
813
814static bool
815write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE childProcess)
816{
817 HANDLE hChild = INVALID_HANDLE_VALUE;
818
819 if (!DuplicateHandle(GetCurrentProcess(),
820 src,
821 childProcess,
822 &hChild,
823 0,
824 TRUE,
825 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
826 {
828 (errmsg_internal("could not duplicate handle to be written to backend parameter file: error code %lu",
829 GetLastError())));
830 return false;
831 }
832
833 *dest = hChild;
834 return true;
835}
836
837
838
839
840
841
842
843
844static bool
845write_inheritable_socket(InheritableSocket *dest, SOCKET src, pid_t childpid)
846{
847 dest->origsocket = src;
849 {
850
851 if (WSADuplicateSocket(src, childpid, &dest->wsainfo) != 0)
852 {
854 (errmsg("could not duplicate socket %d for use in backend: error code %d",
855 (int) src, WSAGetLastError())));
856 return false;
857 }
858 }
859 return true;
860}
861
862
863
864
865static void
866read_inheritable_socket(SOCKET *dest, InheritableSocket *src)
867{
868 SOCKET s;
869
870 if (src->origsocket == PGINVALID_SOCKET || src->origsocket == 0)
871 {
872
873 *dest = src->origsocket;
874 }
875 else
876 {
877
878 s = WSASocket(FROM_PROTOCOL_INFO,
879 FROM_PROTOCOL_INFO,
880 FROM_PROTOCOL_INFO,
881 &src->wsainfo,
882 0,
883 0);
884 if (s == INVALID_SOCKET)
885 {
886 write_stderr("could not create inherited socket: error code %d\n",
887 WSAGetLastError());
888 exit(1);
889 }
891
892
893
894
895
896
898 }
899}
900#endif
901
902static void
903read_backend_variables(char *id, void **startup_data, size_t *startup_data_len)
904{
905 BackendParameters param;
906
907#ifndef WIN32
908
909 FILE *fp;
910
911
913 if (!fp)
914 {
915 write_stderr("could not open backend variables file \"%s\": %m\n", id);
916 exit(1);
917 }
918
919 if (fread(¶m, sizeof(param), 1, fp) != 1)
920 {
921 write_stderr("could not read from backend variables file \"%s\": %m\n", id);
922 exit(1);
923 }
924
925
926 *startup_data_len = param.startup_data_len;
927 if (param.startup_data_len > 0)
928 {
929 *startup_data = palloc(*startup_data_len);
930 if (fread(*startup_data, *startup_data_len, 1, fp) != 1)
931 {
932 write_stderr("could not read startup data from backend variables file \"%s\": %m\n",
933 id);
934 exit(1);
935 }
936 }
937 else
938 *startup_data = NULL;
939
940
942 if (unlink(id) != 0)
943 {
944 write_stderr("could not remove file \"%s\": %m\n", id);
945 exit(1);
946 }
947#else
948
949 HANDLE paramHandle;
950 BackendParameters *paramp;
951
952#ifdef _WIN64
953 paramHandle = (HANDLE) _atoi64(id);
954#else
955 paramHandle = (HANDLE) atol(id);
956#endif
957 paramp = MapViewOfFile(paramHandle, FILE_MAP_READ, 0, 0, 0);
958 if (!paramp)
959 {
960 write_stderr("could not map view of backend variables: error code %lu\n",
961 GetLastError());
962 exit(1);
963 }
964
965 memcpy(¶m, paramp, sizeof(BackendParameters));
966
967
968 *startup_data_len = param.startup_data_len;
969 if (param.startup_data_len > 0)
970 {
971 *startup_data = palloc(paramp->startup_data_len);
972 memcpy(*startup_data, paramp->startup_data, param.startup_data_len);
973 }
974 else
975 *startup_data = NULL;
976
977 if (!UnmapViewOfFile(paramp))
978 {
979 write_stderr("could not unmap view of backend variables: error code %lu\n",
980 GetLastError());
981 exit(1);
982 }
983
984 if (!CloseHandle(paramHandle))
985 {
986 write_stderr("could not close handle to backend parameter variables: error code %lu\n",
987 GetLastError());
988 exit(1);
989 }
990#endif
991
992 restore_backend_variables(¶m);
993}
994
995
996static void
997restore_backend_variables(BackendParameters *param)
998{
1000 {
1004 }
1005
1007
1009
1010#ifdef WIN32
1012#endif
1015
1017
1018#ifdef USE_INJECTION_POINTS
1019 ActiveInjectionPoints = param->ActiveInjectionPoints;
1020#endif
1021
1031
1036
1041
1044
1045#ifdef WIN32
1046 PostmasterHandle = param->PostmasterHandle;
1048#else
1051#endif
1052
1054
1056
1058
1059
1060
1061
1062
1063
1064#ifndef WIN32
1069#endif
1070}
1071
1072#endif
Datum idx(PG_FUNCTION_ARGS)
void AutoVacLauncherMain(const void *startup_data, size_t startup_data_len)
void AutoVacWorkerMain(const void *startup_data, size_t startup_data_len)
void StartupProcessMain(const void *startup_data, size_t startup_data_len)
TimestampTz GetCurrentTimestamp(void)
ConnectionTiming conn_timing
void BackendMain(const void *startup_data, size_t startup_data_len)
void BackgroundWorkerMain(const void *startup_data, size_t startup_data_len)
void BackgroundWriterMain(const void *startup_data, size_t startup_data_len)
#define write_stderr(str)
#define FLEXIBLE_ARRAY_MEMBER
void CheckpointerMain(const void *startup_data, size_t startup_data_len)
void dsm_detach_all(void)
int errmsg_internal(const char *fmt,...)
int errcode_for_file_access(void)
int errhint(const char *fmt,...)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
int MakePGDirectory(const char *directoryName)
void ReserveExternalFD(void)
FILE * AllocateFile(const char *name, const char *mode)
#define PG_TEMP_FILES_DIR
#define PG_TEMP_FILE_PREFIX
struct ClientSocket * MyClientSocket
char pkglib_path[MAXPGPATH]
bool IsPostmasterEnvironment
char my_exec_path[MAXPGPATH]
void InitializeGUCOptions(void)
Assert(PointerIsAligned(start, uint64))
pid_t postmaster_child_launch(BackendType child_type, int child_slot, const void *startup_data, size_t startup_data_len, ClientSocket *client_sock)
static child_process_kind child_process_kinds[]
const char * PostmasterChildName(BackendType child_type)
NamedLWLockTranche * NamedLWLockTrancheArray
int NamedLWLockTrancheRequests
LWLockPadded * MainLWLockArray
void * MemoryContextAlloc(MemoryContext context, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext TopMemoryContext
void IoWorkerMain(const void *startup_data, size_t startup_data_len)
#define IsExternalConnectionBackend(backend_type)
void InitPostmasterChild(void)
void process_shared_preload_libraries(void)
void SetDataDir(const char *dir)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
void PgArchiverMain(const void *startup_data, size_t startup_data_len)
NON_EXEC_STATIC int num_pmchild_slots
NON_EXEC_STATIC volatile PMSignalData * PMSignalState
size_t strlcpy(char *dst, const char *src, size_t siz)
CommandDest whereToSendOutput
int postmaster_alive_fds[2]
void ClosePostmasterPorts(bool am_syslogger)
NON_EXEC_STATIC ProcSignalHeader * ProcSignal
void InitShmemAccess(PGShmemHeader *seghdr)
HANDLE pgwin32_create_signal_listener(pid_t pid)
HANDLE pgwin32_initial_signal_pipe
void ReplSlotSyncWorkerMain(const void *startup_data, size_t startup_data_len)
PGPROC * PreparedXactProcs
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
NON_EXEC_STATIC slock_t * ProcStructLock
TimestampTz socket_create
void(* main_fn)(const void *startup_data, size_t startup_data_len)
void SysLoggerMain(const void *startup_data, size_t startup_data_len)
NON_EXEC_STATIC pg_time_t first_syslogger_file_time
void PGSharedMemoryDetach(void)
unsigned long UsedShmemSegID
void WalReceiverMain(const void *startup_data, size_t startup_data_len)
void WalSummarizerMain(const void *startup_data, size_t startup_data_len)
void WalWriterMain(const void *startup_data, size_t startup_data_len)
void PGSharedMemoryReAttach(void)
void * ShmemProtectiveRegion
int pgwin32_ReserveSharedMemoryRegion(HANDLE hChild)
void PGSharedMemoryNoReAttach(void)
void LocalProcessControlFile(bool reset)