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));

438 sa.nLength = 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(&param->client_sock, client_sock, sizeof(ClientSocket));

739 else

740 memset(&param->client_sock, 0, sizeof(ClientSocket));

741 if (!write_inheritable_socket(&param->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(&param->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(&param, 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(&param, 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(&param);

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)