1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

Refactor EXEC_BACKEND code so that postmaster child processes reattach

to shared memory as soon as possible, ie, right after read_backend_variables.
The effective difference from the original code is that this happens
before instead of after read_nondefault_variables(), which loads GUC
information and is apparently capable of expanding the backend's memory
allocation more than you'd think it should.  This should fix the
failure-to-attach-to-shared-memory reports we've been seeing on Windows.
Also clean up a few bits of unnecessarily grotty EXEC_BACKEND code.
This commit is contained in:
Tom Lane
2004-12-29 21:36:09 +00:00
parent e14018dc5e
commit eee5abce46
7 changed files with 179 additions and 124 deletions

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.113 2004/09/16 16:58:32 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.114 2004/12/29 21:36:05 tgl Exp $
*
* NOTES:
*
@@ -228,6 +228,7 @@ static File fileNameOpenFile(FileName fileName, int fileFlags, int fileMode);
static char *filepath(const char *filename);
static void AtProcExit_Files(int code, Datum arg);
static void CleanupTempFiles(bool isProcExit);
static void RemovePgTempFilesInDir(const char *tmpdirname);
/*
@@ -1482,59 +1483,83 @@ RemovePgTempFiles(void)
{
char db_path[MAXPGPATH];
char temp_path[MAXPGPATH];
char rm_path[MAXPGPATH];
DIR *db_dir;
DIR *temp_dir;
struct dirent *db_de;
struct dirent *temp_de;
/*
* Cycle through pg_tempfiles for all databases and remove old temp
* files.
* Cycle through pgsql_tmp directories for all databases and remove old
* temp files.
*/
snprintf(db_path, sizeof(db_path), "%s/base", DataDir);
if ((db_dir = AllocateDir(db_path)) != NULL)
db_dir = AllocateDir(db_path);
if (db_dir == NULL)
{
while ((db_de = readdir(db_dir)) != NULL)
{
if (strcmp(db_de->d_name, ".") == 0
#ifndef EXEC_BACKEND
/* no PG_TEMP_FILES_DIR in DataDir in non EXEC_BACKEND case */
|| strcmp(db_de->d_name, "..") == 0
#endif
)
continue;
snprintf(temp_path, sizeof(temp_path),
"%s/%s/%s",
db_path, db_de->d_name,
PG_TEMP_FILES_DIR);
if ((temp_dir = AllocateDir(temp_path)) != NULL)
{
while ((temp_de = readdir(temp_dir)) != NULL)
{
if (strcmp(temp_de->d_name, ".") == 0 ||
strcmp(temp_de->d_name, "..") == 0)
continue;
snprintf(rm_path, sizeof(temp_path),
"%s/%s/%s/%s",
db_path, db_de->d_name,
PG_TEMP_FILES_DIR,
temp_de->d_name);
if (strncmp(temp_de->d_name,
PG_TEMP_FILE_PREFIX,
strlen(PG_TEMP_FILE_PREFIX)) == 0)
unlink(rm_path);
else
elog(LOG,
"unexpected file found in temporary-files directory: \"%s\"",
rm_path);
}
FreeDir(temp_dir);
}
}
FreeDir(db_dir);
/* this really should not happen */
elog(LOG, "could not open directory \"%s\": %m", db_path);
return;
}
while ((db_de = readdir(db_dir)) != NULL)
{
if (strcmp(db_de->d_name, ".") == 0 ||
strcmp(db_de->d_name, "..") == 0)
continue;
snprintf(temp_path, sizeof(temp_path), "%s/%s/%s",
db_path, db_de->d_name, PG_TEMP_FILES_DIR);
RemovePgTempFilesInDir(temp_path);
}
FreeDir(db_dir);
/*
* In EXEC_BACKEND case there is a pgsql_tmp directory at the top
* level of DataDir as well.
*/
#ifdef EXEC_BACKEND
snprintf(temp_path, sizeof(temp_path), "%s/%s",
DataDir, PG_TEMP_FILES_DIR);
RemovePgTempFilesInDir(temp_path);
#endif
}
/* Process one pgsql_tmp directory for RemovePgTempFiles */
static void
RemovePgTempFilesInDir(const char *tmpdirname)
{
DIR *temp_dir;
struct dirent *temp_de;
char rm_path[MAXPGPATH];
temp_dir = AllocateDir(tmpdirname);
if (temp_dir == NULL)
{
/* anything except ENOENT is fishy */
if (errno != ENOENT)
elog(LOG,
"could not open temporary-files directory \"%s\": %m",
tmpdirname);
return;
}
while ((temp_de = readdir(temp_dir)) != NULL)
{
if (strcmp(temp_de->d_name, ".") == 0 ||
strcmp(temp_de->d_name, "..") == 0)
continue;
snprintf(rm_path, sizeof(rm_path), "%s/%s",
tmpdirname, temp_de->d_name);
if (strncmp(temp_de->d_name,
PG_TEMP_FILE_PREFIX,
strlen(PG_TEMP_FILE_PREFIX)) == 0)
unlink(rm_path); /* note we ignore any error */
else
elog(LOG,
"unexpected file found in temporary-files directory: \"%s\"",
rm_path);
}
FreeDir(temp_dir);
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.72 2004/09/29 15:15:55 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.73 2004/12/29 21:36:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,6 +19,7 @@
#include "access/xlog.h"
#include "miscadmin.h"
#include "postmaster/bgwriter.h"
#include "postmaster/postmaster.h"
#include "storage/bufmgr.h"
#include "storage/freespace.h"
#include "storage/ipc.h"
@@ -37,14 +38,15 @@
* Creates and initializes shared memory and semaphores.
*
* This is called by the postmaster or by a standalone backend.
* It is also called by a backend forked from the postmaster under
* the EXEC_BACKEND case. (In the non EXEC_BACKEND case, backends
* start life already attached to shared memory.) The initialization
* functions are set up to simply "attach" to pre-existing shared memory
* structures in the latter case. We have to do that in order to
* initialize pointers in local memory that reference the shared structures.
* (In the non EXEC_BACKEND case, these pointer values are inherited via
* fork() from the postmaster.)
* It is also called by a backend forked from the postmaster in the
* EXEC_BACKEND case. In the latter case, the shared memory segment
* already exists and has been physically attached to, but we have to
* initialize pointers in local memory that reference the shared structures,
* because we didn't inherit the correct pointer values from the postmaster
* as we do in the fork() scenario. The easiest way to do that is to run
* through the same code as before. (Note that the called routines mostly
* check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
* This is a bit code-wasteful and could be cleaned up.)
*
* If "makePrivate" is true then we only need private memory, not shared
* memory. This is true for a standalone backend, false for a postmaster.
@@ -101,14 +103,16 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
else
{
/*
* Attach to the shmem segment. (this should only ever be reached
* by EXEC_BACKEND code, and only then with makePrivate == false)
* We are reattaching to an existing shared memory segment.
* This should only be reached in the EXEC_BACKEND case, and
* even then only with makePrivate == false.
*/
#ifdef EXEC_BACKEND
Assert(!makePrivate);
seghdr = PGSharedMemoryCreate(-1, makePrivate, 0);
Assert(UsedShmemSegAddr != NULL);
seghdr = UsedShmemSegAddr;
#else
Assert(false);
elog(PANIC, "should be attached to shared memory already");
#endif
}