PostgreSQL Source Code: src/backend/postmaster/syslogger.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

25

26#include <fcntl.h>

27#include <limits.h>

28#include <signal.h>

31#include <sys/stat.h>

33

54

55

56

57

58

59

60#define READ_BUF_SIZE (2 * PIPE_CHUNK_SIZE)

61

62

63#define LOGROTATE_SIGNAL_FILE "logrotate"

64

65

66

67

68

69

77

78

79

80

91

92

93

94

95

96

97

98

99

100

101

102

103typedef struct

104{

108

109#define NBUFFER_LISTS 256

111

112

113#ifndef WIN32

115#else

117#endif

118

119#ifdef WIN32

120static HANDLE threadHandle = 0;

121static CRITICAL_SECTION sysloggerSection;

122#endif

123

124

125

126

128

129

130

131#ifdef EXEC_BACKEND

132static int syslogger_fdget(FILE *file);

133static FILE *syslogger_fdopen(int fd);

134#endif

135static void process_pipe_input(char *logbuffer, int *bytes_in_logbuffer);

136static void flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer);

138 bool allow_errors);

139

140#ifdef WIN32

141static unsigned int __stdcall pipeThread(void *arg);

142#endif

143static void logfile_rotate(bool time_based_rotation, int size_rotation_for);

145 int size_rotation_for, pg_time_t fntime,

146 int target_dest, char **last_file_name,

147 FILE **logFile);

152

153typedef struct

154{

159

160

161

162

163

164void

165SysLoggerMain(const void *startup_data, size_t startup_data_len)

166{

167#ifndef WIN32

169 int bytes_in_logbuffer = 0;

170#endif

171 char *currentLogDir;

172 char *currentLogFilename;

173 int currentLogRotationAge;

176

177

178

179

180

181

182

183

184#ifdef EXEC_BACKEND

185 {

187

188 Assert(startup_data_len == sizeof(*slsdata));

192 }

193#else

194 Assert(startup_data_len == 0);

195#endif

196

197

198

199

200

202 {

205 }

206

208

211

212

213

214

215

216

217

218

220 {

221 int fd = open(DEVNULL, O_WRONLY, 0);

222

223

224

225

226

227

228

229

230

231

232

233

236 if (fd != -1)

237 {

241 }

242 }

243

244

245

246

247

248

249#ifdef WIN32

250 else

252#endif

253

254

255

256

257

258

259#ifndef WIN32

263#else

267#endif

268

269

270

271

272

273

274

275

276

278

286

287

288

289

291

292 sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);

293

294#ifdef WIN32

295

296 InitializeCriticalSection(&sysloggerSection);

297 EnterCriticalSection(&sysloggerSection);

298

299 threadHandle = (HANDLE) _beginthreadex(NULL, 0, pipeThread, NULL, 0, NULL);

300 if (threadHandle == 0)

301 elog(FATAL, "could not create syslogger data transfer thread: %m");

302#endif

303

304

305

306

307

308

314

315

319

322

323

324

325

326

327

329

330

331

332

333

334

335

336

337

338

339

342#ifndef WIN32

344#endif

345

346

347 for (;;)

348 {

349 bool time_based_rotation = false;

350 int size_rotation_for = 0;

351 long cur_timeout;

353

354#ifndef WIN32

355 int rc;

356#endif

357

358

360

361

362

363

365 {

368

369

370

371

372

373

375 {

376 pfree(currentLogDir);

379

380

381

382

384 }

385 if (strcmp(Log_filename, currentLogFilename) != 0)

386 {

387 pfree(currentLogFilename);

390 }

391

392

393

394

395

399

400

401

402

403

407

408

409

410

411

413 {

416 }

417

418

419

420

421

423 {

426 }

427

428

429

430

431

432

434 }

435

437 {

438

442 }

443

445 {

446

448 {

451 }

454 {

457 }

460 {

463 }

464 }

465

467 {

468

469

470

471

472 if (!time_based_rotation && size_rotation_for == 0)

476 logfile_rotate(time_based_rotation, size_rotation_for);

477 }

478

479

480

481

482

483

484

485

486

487

488

489

490

492 {

494

496 if (delay > 0)

497 {

498 if (delay > INT_MAX / 1000)

499 delay = INT_MAX / 1000;

500 cur_timeout = delay * 1000L;

501 }

502 else

503 cur_timeout = 0;

504 }

505 else

506 cur_timeout = -1L;

507

508

509

510

511#ifndef WIN32

513 WAIT_EVENT_SYSLOGGER_MAIN);

514

516 {

517 int bytesRead;

518

520 logbuffer + bytes_in_logbuffer,

521 sizeof(logbuffer) - bytes_in_logbuffer);

522 if (bytesRead < 0)

523 {

524 if (errno != EINTR)

527 errmsg("could not read from logger pipe: %m")));

528 }

529 else if (bytesRead > 0)

530 {

531 bytes_in_logbuffer += bytesRead;

533 continue;

534 }

535 else

536 {

537

538

539

540

541

542

544

545

547 }

548 }

549#else

550

551

552

553

554

555

556

557

558

559

560 LeaveCriticalSection(&sysloggerSection);

561

563 WAIT_EVENT_SYSLOGGER_MAIN);

564

565 EnterCriticalSection(&sysloggerSection);

566#endif

567

569 {

570

571

572

573

576

577

578

579

580

581

582

583

585 }

586 }

587}

588

589

590

591

592int

594{

595 pid_t sysloggerPid;

597#ifdef EXEC_BACKEND

599#endif

600

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620#ifndef WIN32

622 {

626 errmsg("could not create pipe for syslog: %m")));

627 }

628#else

630 {

631 SECURITY_ATTRIBUTES sa;

632

633 memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));

634 sa.nLength = sizeof(SECURITY_ATTRIBUTES);

635 sa.bInheritHandle = TRUE;

636

640 errmsg("could not create pipe for syslog: %m")));

641 }

642#endif

643

644

645

646

648

649

650

651

652

653

654

655

656

657

658

659

660

662

664

666

668

669

670

671

672

673

675 {

677

679

681 }

682

683

684

685

686

687

689 {

691

693

695 }

696

697#ifdef EXEC_BACKEND

702 &startup_data, sizeof(startup_data), NULL);

703#else

705 NULL, 0, NULL);

706#endif

707

708 if (sysloggerPid == -1)

709 {

711 (errmsg("could not fork system logger: %m")));

712 return 0;

713 }

714

715

716

717

719 {

720#ifdef WIN32

721 int fd;

722#endif

723

724

725

726

727

728

730 (errmsg("redirecting log output to logging collector process"),

731 errhint("Future log output will appear in directory \"%s\".",

733

734#ifndef WIN32

739 errmsg("could not redirect stdout: %m")));

740 fflush(stderr);

744 errmsg("could not redirect stderr: %m")));

745

748#else

749

750

751

752

753

754

755 fflush(stderr);

756 fd = _open_osfhandle((intptr_t) syslogPipe[1],

757 _O_APPEND | _O_BINARY);

761 errmsg("could not redirect stderr: %m")));

764

765

766

767

768

769

771#endif

773 }

774

775

779 {

782 }

784 {

787 }

788 return (int) sysloggerPid;

789}

790

791

792#ifdef EXEC_BACKEND

793

794

795

796

797

798

799

800static int

801syslogger_fdget(FILE *file)

802{

803#ifndef WIN32

804 if (file != NULL)

805 return fileno(file);

806 else

807 return -1;

808#else

809 if (file != NULL)

810 return (int) _get_osfhandle(_fileno(file));

811 else

812 return 0;

813#endif

814}

815

816

817

818

819

820

821

822static FILE *

823syslogger_fdopen(int fd)

824{

825 FILE *file = NULL;

826

827#ifndef WIN32

828 if (fd != -1)

829 {

830 file = fdopen(fd, "a");

831 setvbuf(file, NULL, PG_IOLBF, 0);

832 }

833#else

834 if (fd != 0)

835 {

836 fd = _open_osfhandle(fd, _O_APPEND | _O_TEXT);

837 if (fd > 0)

838 {

839 file = fdopen(fd, "a");

840 setvbuf(file, NULL, PG_IOLBF, 0);

841 }

842 }

843#endif

844

845 return file;

846}

847#endif

848

849

850

851

852

853

854

855

856

857

858

859

860

861

862

863

864

865

866

867

868

869

870

871

872

873

874

875

876

877

878static void

880{

881 char *cursor = logbuffer;

882 int count = *bytes_in_logbuffer;

884

885

887 {

889 int chunklen;

890 bits8 dest_flags;

891

892

897 if (p.nuls[0] == '\0' && p.nuls[1] == '\0' &&

899 p.pid != 0 &&

901 {

902 List *buffer_list;

905 *free_slot = NULL;

907

909

910

911 if (count < chunklen)

912 break;

913

920 else

921 {

922

924 }

925

926

928 foreach(cell, buffer_list)

929 {

931

932 if (buf->pid == p.pid)

933 {

934 existing_slot = buf;

935 break;

936 }

937 if (buf->pid == 0 && free_slot == NULL)

938 free_slot = buf;

939 }

940

942 {

943

944

945

946 if (existing_slot != NULL)

947 {

948

949 str = &(existing_slot->data);

953 }

954 else

955 {

956

957 if (free_slot == NULL)

958 {

959

960

961

962

964 buffer_list = lappend(buffer_list, free_slot);

966 }

967 free_slot->pid = p.pid;

968 str = &(free_slot->data);

973 }

974 }

975 else

976 {

977

978

979

980

981 if (existing_slot != NULL)

982 {

983 str = &(existing_slot->data);

988

989 existing_slot->pid = 0;

991 }

992 else

993 {

994

997 }

998 }

999

1000

1002 count -= chunklen;

1003 }

1004 else

1005 {

1006

1007

1008

1009

1010

1011

1012

1013

1014

1015

1016

1017 for (chunklen = 1; chunklen < count; chunklen++)

1018 {

1019 if (cursor[chunklen] == '\0')

1020 break;

1021 }

1022

1025 count -= chunklen;

1026 }

1027 }

1028

1029

1030 if (count > 0 && cursor != logbuffer)

1031 memmove(logbuffer, cursor, count);

1032 *bytes_in_logbuffer = count;

1033}

1034

1035

1036

1037

1038

1039

1040

1041static void

1043{

1044 int i;

1045

1046

1048 {

1051

1052 foreach(cell, list)

1053 {

1055

1056 if (buf->pid != 0)

1057 {

1059

1062

1063 buf->pid = 0;

1065 }

1066 }

1067 }

1068

1069

1070

1071

1072

1073 if (*bytes_in_logbuffer > 0)

1076 *bytes_in_logbuffer = 0;

1077}

1078

1079

1080

1081

1082

1083

1084

1085

1086

1087

1088

1089

1090

1091

1092void

1094{

1095 int rc;

1097

1098

1099

1100

1101

1102

1103

1104

1105

1106

1107

1108

1109

1110

1115 else

1117

1118 rc = fwrite(buffer, 1, count, logfile);

1119

1120

1121

1122

1123

1124

1125

1126 if (rc != count)

1127 write_stderr("could not write to log file: %m\n");

1128}

1129

1130#ifdef WIN32

1131

1132

1133

1134

1135

1136

1137

1138

1139static unsigned int __stdcall

1140pipeThread(void *arg)

1141{

1143 int bytes_in_logbuffer = 0;

1144

1145 for (;;)

1146 {

1147 DWORD bytesRead;

1148 BOOL result;

1149

1151 logbuffer + bytes_in_logbuffer,

1152 sizeof(logbuffer) - bytes_in_logbuffer,

1153 &bytesRead, 0);

1154

1155

1156

1157

1158

1159

1160

1161 EnterCriticalSection(&sysloggerSection);

1162 if (!result)

1163 {

1164 DWORD error = GetLastError();

1165

1166 if (error == ERROR_HANDLE_EOF ||

1167 error == ERROR_BROKEN_PIPE)

1168 break;

1172 errmsg("could not read from logger pipe: %m")));

1173 }

1174 else if (bytesRead > 0)

1175 {

1176 bytes_in_logbuffer += bytesRead;

1178 }

1179

1180

1181

1182

1183

1185 {

1192 }

1193 LeaveCriticalSection(&sysloggerSection);

1194 }

1195

1196

1198

1199

1201

1202

1204

1205 LeaveCriticalSection(&sysloggerSection);

1206 _endthread();

1207 return 0;

1208}

1209#endif

1210

1211

1212

1213

1214

1215

1216

1217

1218static FILE *

1220{

1221 FILE *fh;

1222 mode_t oumask;

1223

1224

1225

1226

1227

1230 umask(oumask);

1231

1232 if (fh)

1233 {

1234 setvbuf(fh, NULL, PG_IOLBF, 0);

1235

1236#ifdef WIN32

1237

1238 _setmode(_fileno(fh), _O_TEXT);

1239#endif

1240 }

1241 else

1242 {

1243 int save_errno = errno;

1244

1247 errmsg("could not open log file \"%s\": %m",

1249 errno = save_errno;

1250 }

1251

1252 return fh;

1253}

1254

1255

1256

1257

1258

1259

1260

1261

1262

1263static bool

1265 pg_time_t fntime, int target_dest,

1266 char **last_file_name, FILE **logFile)

1267{

1268 char *logFileExt = NULL;

1270 FILE *fh;

1271

1272

1273

1274

1275

1276

1277

1280 {

1281 if (*logFile != NULL)

1282 fclose(*logFile);

1283 *logFile = NULL;

1284 if (*last_file_name != NULL)

1285 pfree(*last_file_name);

1286 *last_file_name = NULL;

1287 return true;

1288 }

1289

1290

1291

1292

1293

1294 if (!time_based_rotation && (size_rotation_for & target_dest) == 0)

1295 return true;

1296

1297

1299 logFileExt = NULL;

1301 logFileExt = ".csv";

1303 logFileExt = ".json";

1304 else

1305 {

1306

1308 }

1309

1310

1312

1313

1314

1315

1316

1317

1318

1320 *last_file_name != NULL &&

1321 strcmp(filename, *last_file_name) != 0)

1323 else

1325

1326 if (!fh)

1327 {

1328

1329

1330

1331

1332

1333

1334 if (errno != ENFILE && errno != EMFILE)

1335 {

1337 (errmsg("disabling automatic rotation (use SIGHUP to re-enable)")));

1339 }

1340

1343 return false;

1344 }

1345

1346

1347 if (*logFile != NULL)

1348 fclose(*logFile);

1349 *logFile = fh;

1350

1351

1352 if (*last_file_name != NULL)

1353 pfree(*last_file_name);

1355

1356 return true;

1357}

1358

1359

1360

1361

1362static void

1364{

1366

1368

1369

1370

1371

1372

1373

1374 if (time_based_rotation)

1376 else

1377 fntime = time(NULL);

1378

1379

1380 if (logfile\_rotate\_dest(time_based_rotation, size_rotation_for, fntime,

1383 return;

1384

1385

1386 if (logfile\_rotate\_dest(time_based_rotation, size_rotation_for, fntime,

1389 return;

1390

1391

1392 if (logfile\_rotate\_dest(time_based_rotation, size_rotation_for, fntime,

1395 return;

1396

1398

1400}

1401

1402

1403

1404

1405

1406

1407

1408

1409

1410

1411static char *

1413{

1415 int len;

1416

1418

1420

1422

1423

1426

1427 if (suffix != NULL)

1428 {

1430 if (len > 4 && (strcmp(filename + (len - 4), ".log") == 0))

1431 len -= 4;

1433 }

1434

1436}

1437

1438

1439

1440

1441static void

1443{

1446 int rotinterval;

1447

1448

1450 return;

1451

1452

1453

1454

1455

1456

1457

1462 now -= now % rotinterval;

1463 now += rotinterval;

1466}

1467

1468

1469

1470

1471

1472

1473

1474

1475

1476static void

1478{

1479 FILE *fh;

1480 mode_t oumask;

1481

1485 {

1489 errmsg("could not remove file \"%s\": %m",

1491 return;

1492 }

1493

1494

1497 umask(oumask);

1498

1499 if (fh)

1500 {

1501 setvbuf(fh, NULL, PG_IOLBF, 0);

1502

1503#ifdef WIN32

1504

1505 _setmode(_fileno(fh), _O_TEXT);

1506#endif

1507 }

1508 else

1509 {

1512 errmsg("could not open file \"%s\": %m",

1514 return;

1515 }

1516

1518 {

1520 {

1523 errmsg("could not write file \"%s\": %m",

1525 fclose(fh);

1526 return;

1527 }

1528 }

1529

1531 {

1533 {

1536 errmsg("could not write file \"%s\": %m",

1538 fclose(fh);

1539 return;

1540 }

1541 }

1542

1544 {

1546 {

1549 errmsg("could not write file \"%s\": %m",

1551 fclose(fh);

1552 return;

1553 }

1554 }

1555 fclose(fh);

1556

1560 errmsg("could not rename file \"%s\" to \"%s\": %m",

1562}

1563

1564

1565

1566

1567

1568

1569

1570

1571

1572

1573bool

1575{

1576 struct stat stat_buf;

1577

1579 return true;

1580

1581 return false;

1582}

1583

1584

1585

1586

1587void

1589{

1591}

1592

1593

1594static void

1596{

1599}

Datum now(PG_FUNCTION_ARGS)

#define write_stderr(str)

#define fprintf(file, fmt, msg)

int errcode_for_socket_access(void)

int errmsg_internal(const char *fmt,...)

int errcode_for_file_access(void)

int errhint(const char *fmt,...)

int errmsg(const char *fmt,...)

#define LOG_DESTINATION_JSONLOG

#define LOG_DESTINATION_STDERR

#define ereport(elevel,...)

#define LOG_DESTINATION_CSVLOG

int MakePGDirectory(const char *directoryName)

void ProcessConfigFile(GucContext context)

Assert(PointerIsAligned(start, uint64))

volatile sig_atomic_t ConfigReloadPending

void SignalHandlerForConfigReload(SIGNAL_ARGS)

void SetLatch(Latch *latch)

void ResetLatch(Latch *latch)

pid_t postmaster_child_launch(BackendType child_type, int child_slot, const void *startup_data, size_t startup_data_len, ClientSocket *client_sock)

List * lappend(List *list, void *datum)

char * pstrdup(const char *in)

void pfree(void *pointer)

MemoryContext PostmasterContext

void MemoryContextDelete(MemoryContext context)

BackendType MyBackendType

PGDLLIMPORT const uint8 pg_number_of_ones[256]

static PgChecksumMode mode

size_t pg_strftime(char *s, size_t maxsize, const char *format, const struct pg_tm *t)

struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)

PGDLLIMPORT pg_tz * log_timezone

size_t strlcpy(char *dst, const char *src, size_t siz)

CommandDest whereToSendOutput

static int fd(const char *x, int i)

void init_ps_display(const char *fixed_part)

void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)

void initStringInfo(StringInfo str)

bool Log_truncate_on_rotation

static bool rotation_disabled

static void logfile_rotate(bool time_based_rotation, int size_rotation_for)

static bool pipe_eof_seen

void SysLoggerMain(const void *startup_data, size_t startup_data_len)

static bool logfile_rotate_dest(bool time_based_rotation, int size_rotation_for, pg_time_t fntime, int target_dest, char **last_file_name, FILE **logFile)

bool CheckLogrotateSignal(void)

static char * logfile_getname(pg_time_t timestamp, const char *suffix)

#define LOGROTATE_SIGNAL_FILE

static FILE * logfile_open(const char *filename, const char *mode, bool allow_errors)

static void update_metainfo_datafile(void)

static char * last_csv_file_name

NON_EXEC_STATIC pg_time_t first_syslogger_file_time

static void process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)

void RemoveLogrotateSignalFiles(void)

void write_syslogger_file(const char *buffer, int count, int destination)

static pg_time_t next_rotation_time

static volatile sig_atomic_t rotation_requested

static List * buffer_lists[NBUFFER_LISTS]

static void sigUsr1Handler(SIGNAL_ARGS)

static void set_next_rotation_time(void)

static void flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer)

int SysLogger_Start(int child_slot)

static FILE * jsonlogFile

static char * last_json_file_name

static char * last_sys_file_name

#define PIPE_PROTO_DEST_JSONLOG

#define PIPE_PROTO_IS_LAST

#define PIPE_PROTO_DEST_CSVLOG

#define LOG_METAINFO_DATAFILE_TMP

#define PIPE_PROTO_DEST_STDERR

#define LOG_METAINFO_DATAFILE

int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, void *user_data)

int WaitEventSetWait(WaitEventSet *set, long timeout, WaitEvent *occurred_events, int nevents, uint32 wait_event_info)

WaitEventSet * CreateWaitEventSet(ResourceOwner resowner, int nevents)

#define WL_SOCKET_READABLE

void _dosmaperr(unsigned long)