|
7 | 7 | *
|
8 | 8 | *
|
9 | 9 | * IDENTIFICATION
|
10 |
| - * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.37 1999/11/24 16:52:42 momjian Exp $ |
| 10 | + * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.38 2000/01/09 12:15:57 ishii Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
14 | 14 | #include <sys/param.h>
|
15 | 15 | #include <sys/types.h>
|
| 16 | +#include <signal.h> |
16 | 17 | #include <sys/stat.h>
|
17 | 18 | #include <sys/file.h>
|
18 | 19 | #include <unistd.h>
|
@@ -462,3 +463,156 @@ SetUserId()
|
462 | 463 | ShadowRelationName);
|
463 | 464 | UserId = (Oid) ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
|
464 | 465 | }
|
| 466 | + |
| 467 | +/*------------------------------------------------------------------------- |
| 468 | + * |
| 469 | + * posmaster pid file stuffs. $DATADIR/postmaster.pid is created when: |
| 470 | + * |
| 471 | + * (1) postmaster starts. In this case pid > 0. |
| 472 | + * (2) postgres starts in standalone mode. In this case |
| 473 | + * pid < 0 |
| 474 | + * |
| 475 | + * to gain an interlock. |
| 476 | + * |
| 477 | + * SetPidFname(datadir) |
| 478 | + * Remember the the pid file name. This is neccesary |
| 479 | + * UnlinkPidFile() is called from proc_exit(). |
| 480 | + * |
| 481 | + * GetPidFname(datadir) |
| 482 | + * Get the pid file name. SetPidFname() should be called |
| 483 | + * before GetPidFname() gets called. |
| 484 | + * |
| 485 | + * UnlinkPidFile() |
| 486 | + * This is called from proc_exit() and unlink the pid file. |
| 487 | + * |
| 488 | + * SetPidFile(pid_t pid) |
| 489 | + * Create the pid file. On failure, it checks if the process |
| 490 | + * actually exists or not. SetPidFname() should be called |
| 491 | + * in prior to calling SetPidFile(). |
| 492 | + * |
| 493 | + *------------------------------------------------------------------------- |
| 494 | + */ |
| 495 | + |
| 496 | +/* |
| 497 | + * Path to pid file. proc_exit() remember it to unlink the file. |
| 498 | + */ |
| 499 | +static char PidFile[MAXPGPATH]; |
| 500 | + |
| 501 | +/* |
| 502 | + * Remove the pid file. This function is called from proc_exit. |
| 503 | + */ |
| 504 | +void UnlinkPidFile(void) |
| 505 | +{ |
| 506 | + unlink(PidFile); |
| 507 | +} |
| 508 | + |
| 509 | +/* |
| 510 | + * Set path to the pid file |
| 511 | + */ |
| 512 | +void SetPidFname(char * datadir) |
| 513 | +{ |
| 514 | + snprintf(PidFile, sizeof(PidFile), "%s/%s", datadir, PIDFNAME); |
| 515 | +} |
| 516 | + |
| 517 | +/* |
| 518 | + * Get path to the pid file |
| 519 | + */ |
| 520 | +char *GetPidFname(void) |
| 521 | +{ |
| 522 | + return(PidFile); |
| 523 | +} |
| 524 | + |
| 525 | +/* |
| 526 | + * Create the pid file |
| 527 | + */ |
| 528 | +int SetPidFile(pid_t pid) |
| 529 | +{ |
| 530 | + int fd; |
| 531 | + char *pidfile; |
| 532 | + char pidstr[32]; |
| 533 | + int len; |
| 534 | + pid_t post_pid; |
| 535 | + int is_postgres = 0; |
| 536 | + |
| 537 | + /* |
| 538 | + * Creating pid file |
| 539 | + */ |
| 540 | + pidfile = GetPidFname(); |
| 541 | + fd = open(pidfile, O_RDWR | O_CREAT | O_EXCL, 0600); |
| 542 | + if (fd < 0) { |
| 543 | + /* |
| 544 | + * Couldn't create the pid file. Probably |
| 545 | + * it already exists. Read the file to see if the process |
| 546 | + * actually exists |
| 547 | + */ |
| 548 | + fd = open(pidfile, O_RDONLY, 0600); |
| 549 | + if (fd < 0) { |
| 550 | + fprintf(stderr, "Can't open pid file: %s\n", pidfile); |
| 551 | + fprintf(stderr, "Please check the permission and try again.\n"); |
| 552 | + return(-1); |
| 553 | + } |
| 554 | + if ((len = read(fd, pidstr, sizeof(pidstr)-1)) < 0) { |
| 555 | + fprintf(stderr, "Can't read pid file: %s\n", pidfile); |
| 556 | + fprintf(stderr, "Please check the permission and try again.\n"); |
| 557 | + close(fd); |
| 558 | + return(-1); |
| 559 | + } |
| 560 | + close(fd); |
| 561 | + |
| 562 | + /* |
| 563 | + * Check to see if the process actually exists |
| 564 | + */ |
| 565 | + pidstr[len] = '\0'; |
| 566 | + post_pid = (pid_t)atoi(pidstr); |
| 567 | + |
| 568 | + /* if pid < 0, the pid is for postgres, not postmatser */ |
| 569 | + if (post_pid < 0) { |
| 570 | + is_postgres++; |
| 571 | + post_pid = -post_pid; |
| 572 | + } |
| 573 | + |
| 574 | + if (post_pid == 0 || (post_pid > 0 && kill(post_pid, 0) < 0)) { |
| 575 | + /* |
| 576 | + * No, the process did not exist. Unlink |
| 577 | + * the file and try to create it |
| 578 | + */ |
| 579 | + if (unlink(pidfile) < 0) { |
| 580 | + fprintf(stderr, "Can't remove pid file: %s\n", pidfile); |
| 581 | + fprintf(stderr, "The file seems accidently left, but I couldn't remove it.\n"); |
| 582 | + fprintf(stderr, "Please remove the file by hand and try again.\n"); |
| 583 | + return(-1); |
| 584 | + } |
| 585 | + fd = open(pidfile, O_RDWR | O_CREAT | O_EXCL, 0600); |
| 586 | + if (fd < 0) { |
| 587 | + fprintf(stderr, "Can't create pid file: %s\n", pidfile); |
| 588 | + fprintf(stderr, "Please check the permission and try again.\n"); |
| 589 | + return(-1); |
| 590 | + } |
| 591 | + } else { |
| 592 | + /* |
| 593 | + * Another postmaster is running |
| 594 | + */ |
| 595 | + fprintf(stderr, "Can't create pid file: %s\n", pidfile); |
| 596 | + if (is_postgres) { |
| 597 | + fprintf(stderr, "Is another postgres (pid: %d) running?\n", post_pid); |
| 598 | + } |
| 599 | + else |
| 600 | + { |
| 601 | + fprintf(stderr, "Is another postmaster (pid: %s) running?\n", pidstr); |
| 602 | + } |
| 603 | + return(-1); |
| 604 | + } |
| 605 | + } |
| 606 | + |
| 607 | + sprintf(pidstr, "%d", pid); |
| 608 | + if (write(fd, pidstr, strlen(pidstr)) != strlen(pidstr)) { |
| 609 | + fprintf(stderr,"Write to pid file failed\n"); |
| 610 | + fprintf(stderr, "Please check the permission and try again.\n"); |
| 611 | + close(fd); |
| 612 | + unlink(pidfile); |
| 613 | + return(-1); |
| 614 | + } |
| 615 | + close(fd); |
| 616 | + |
| 617 | + return(0); |
| 618 | +} |
0 commit comments