Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f763b77

Browse files
committed
Fix pg_upgrade to cope with non-default unix_socket_directory scenarios.
When starting either an old or new postmaster, force it to place its Unix socket in the current directory. This makes it even harder for accidental connections to occur during pg_upgrade, and also works around some scenarios where the default socket location isn't usable. (For example, if the default location is something other than "/tmp", it might not exist during "make check".) When checking an already-running old postmaster, find out its actual socket directory location from postmaster.pid, if possible. This dodges problems with an old postmaster having a configured location different from the default built into pg_upgrade's libpq. We can't find that out if the old postmaster is pre-9.1, so also document how to cope with such scenarios manually. In support of this, centralize handling of the connection-related command line options passed to pg_upgrade's subsidiary programs, such as pg_dump. This should make future changes easier. Bruce Momjian and Tom Lane
1 parent c1f3c04 commit f763b77

File tree

7 files changed

+149
-20
lines changed

7 files changed

+149
-20
lines changed

contrib/pg_upgrade/check.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ issue_warnings(char *sequence_script_file_name)
184184
{
185185
prep_status("Adjusting sequences");
186186
exec_prog(UTILITY_LOG_FILE, NULL, true,
187-
"\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
188-
new_cluster.bindir, new_cluster.port, os_info.user,
187+
"\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
188+
new_cluster.bindir, cluster_conn_opts(&new_cluster),
189189
sequence_script_file_name);
190190
unlink(sequence_script_file_name);
191191
check_ok();

contrib/pg_upgrade/dump.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ generate_old_dump(void)
2424
* restores the frozenid's for databases and relations.
2525
*/
2626
exec_prog(UTILITY_LOG_FILE, NULL, true,
27-
"\"%s/pg_dumpall\" --port %d --username \"%s\" --schema-only --binary-upgrade %s -f %s",
28-
new_cluster.bindir, old_cluster.port, os_info.user,
27+
"\"%s/pg_dumpall\" %s --schema-only --binary-upgrade %s -f %s",
28+
new_cluster.bindir, cluster_conn_opts(&old_cluster),
2929
log_opts.verbose ? "--verbose" : "",
3030
ALL_DUMP_FILE);
3131
check_ok();

contrib/pg_upgrade/option.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include "postgres.h"
1111

12+
#include "miscadmin.h"
13+
1214
#include "pg_upgrade.h"
1315

1416
#include <getopt_long.h>
@@ -376,3 +378,64 @@ adjust_data_dir(ClusterInfo *cluster)
376378

377379
check_ok();
378380
}
381+
382+
383+
/*
384+
* get_sock_dir
385+
*
386+
* Identify the socket directory to use for this cluster. If we're doing
387+
* a live check (old cluster only), we need to find out where the postmaster
388+
* is listening. Otherwise, we're going to put the socket into the current
389+
* directory.
390+
*/
391+
void
392+
get_sock_dir(ClusterInfo *cluster, bool live_check)
393+
{
394+
#ifdef HAVE_UNIX_SOCKETS
395+
if (!live_check)
396+
{
397+
/* Use the current directory for the socket */
398+
cluster->sockdir = pg_malloc(MAXPGPATH);
399+
if (!getcwd(cluster->sockdir, MAXPGPATH))
400+
pg_log(PG_FATAL, "cannot find current directory\n");
401+
}
402+
else
403+
{
404+
/*
405+
* If we are doing a live check, we will use the old cluster's Unix
406+
* domain socket directory so we can connect to the live server.
407+
*/
408+
409+
/* sockdir was added to postmaster.pid in PG 9.1 */
410+
if (GET_MAJOR_VERSION(cluster->major_version) >= 901)
411+
{
412+
char filename[MAXPGPATH];
413+
FILE *fp;
414+
int i;
415+
416+
snprintf(filename, sizeof(filename), "%s/postmaster.pid",
417+
cluster->pgdata);
418+
if ((fp = fopen(filename, "r")) == NULL)
419+
pg_log(PG_FATAL, "Could not get socket directory of the old server\n");
420+
421+
cluster->sockdir = pg_malloc(MAXPGPATH);
422+
for (i = 0; i < LOCK_FILE_LINE_SOCKET_DIR; i++)
423+
if (fgets(cluster->sockdir, MAXPGPATH, fp) == NULL)
424+
pg_log(PG_FATAL, "Could not get socket directory of the old server\n");
425+
426+
fclose(fp);
427+
428+
/* Remove trailing newline */
429+
if (strchr(cluster->sockdir, '\n') != NULL)
430+
*strchr(cluster->sockdir, '\n') = '\0';
431+
}
432+
else
433+
{
434+
/* Can't get live sockdir, so assume the default is OK. */
435+
cluster->sockdir = NULL;
436+
}
437+
}
438+
#else /* !HAVE_UNIX_SOCKETS */
439+
cluster->sockdir = NULL;
440+
#endif
441+
}

contrib/pg_upgrade/pg_upgrade.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ main(int argc, char **argv)
8888
check_cluster_versions();
8989
check_cluster_compatibility(live_check);
9090

91+
get_sock_dir(&old_cluster, live_check);
92+
get_sock_dir(&new_cluster, false);
93+
9194
check_old_cluster(live_check, &sequence_script_file_name);
9295

9396

@@ -211,8 +214,8 @@ prepare_new_cluster(void)
211214
*/
212215
prep_status("Analyzing all rows in the new cluster");
213216
exec_prog(UTILITY_LOG_FILE, NULL, true,
214-
"\"%s/vacuumdb\" --port %d --username \"%s\" --all --analyze %s",
215-
new_cluster.bindir, new_cluster.port, os_info.user,
217+
"\"%s/vacuumdb\" %s --all --analyze %s",
218+
new_cluster.bindir, cluster_conn_opts(&new_cluster),
216219
log_opts.verbose ? "--verbose" : "");
217220
check_ok();
218221

@@ -224,8 +227,8 @@ prepare_new_cluster(void)
224227
*/
225228
prep_status("Freezing all rows on the new cluster");
226229
exec_prog(UTILITY_LOG_FILE, NULL, true,
227-
"\"%s/vacuumdb\" --port %d --username \"%s\" --all --freeze %s",
228-
new_cluster.bindir, new_cluster.port, os_info.user,
230+
"\"%s/vacuumdb\" %s --all --freeze %s",
231+
new_cluster.bindir, cluster_conn_opts(&new_cluster),
229232
log_opts.verbose ? "--verbose" : "");
230233
check_ok();
231234

@@ -261,8 +264,8 @@ prepare_new_databases(void)
261264
* the template0 template.
262265
*/
263266
exec_prog(RESTORE_LOG_FILE, NULL, true,
264-
"\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
265-
new_cluster.bindir, new_cluster.port, os_info.user,
267+
"\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
268+
new_cluster.bindir, cluster_conn_opts(&new_cluster),
266269
GLOBALS_DUMP_FILE);
267270
check_ok();
268271

@@ -290,8 +293,8 @@ create_new_objects(void)
290293

291294
prep_status("Restoring database schema to new cluster");
292295
exec_prog(RESTORE_LOG_FILE, NULL, true,
293-
"\"%s/psql\" " EXEC_PSQL_ARGS " --port %d --username \"%s\" -f \"%s\"",
294-
new_cluster.bindir, new_cluster.port, os_info.user,
296+
"\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
297+
new_cluster.bindir, cluster_conn_opts(&new_cluster),
295298
DB_DUMP_FILE);
296299
check_ok();
297300

contrib/pg_upgrade/pg_upgrade.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ typedef struct
226226
char *bindir; /* pathname for cluster's executable directory */
227227
char *pgopts; /* options to pass to the server, like pg_ctl
228228
* -o */
229+
char *sockdir; /* directory for Unix Domain socket, if any */
229230
unsigned short port; /* port number where postmaster is waiting */
230231
uint32 major_version; /* PG_VERSION of cluster */
231232
char major_version_str[64]; /* string PG_VERSION of cluster */
@@ -387,6 +388,7 @@ void print_maps(FileNameMap *maps, int n,
387388

388389
void parseCommandLine(int argc, char *argv[]);
389390
void adjust_data_dir(ClusterInfo *cluster);
391+
void get_sock_dir(ClusterInfo *cluster, bool live_check);
390392

391393
/* relfilenode.c */
392394

@@ -407,6 +409,8 @@ PGresult *
407409
executeQueryOrDie(PGconn *conn, const char *fmt,...)
408410
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
409411

412+
char *cluster_conn_opts(ClusterInfo *cluster);
413+
410414
void start_postmaster(ClusterInfo *cluster);
411415
void stop_postmaster(bool fast);
412416
uint32 get_major_server_version(ClusterInfo *cluster);

contrib/pg_upgrade/server.c

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,54 @@ connectToServer(ClusterInfo *cluster, const char *db_name)
4646
/*
4747
* get_db_conn()
4848
*
49-
* get database connection
49+
* get database connection, using named database + standard params for cluster
5050
*/
5151
static PGconn *
5252
get_db_conn(ClusterInfo *cluster, const char *db_name)
5353
{
54-
char conn_opts[MAXPGPATH];
54+
char conn_opts[2 * NAMEDATALEN + MAXPGPATH + 100];
5555

56-
snprintf(conn_opts, sizeof(conn_opts),
57-
"dbname = '%s' user = '%s' port = %d", db_name, os_info.user,
58-
cluster->port);
56+
if (cluster->sockdir)
57+
snprintf(conn_opts, sizeof(conn_opts),
58+
"dbname = '%s' user = '%s' host = '%s' port = %d",
59+
db_name, os_info.user, cluster->sockdir, cluster->port);
60+
else
61+
snprintf(conn_opts, sizeof(conn_opts),
62+
"dbname = '%s' user = '%s' port = %d",
63+
db_name, os_info.user, cluster->port);
5964

6065
return PQconnectdb(conn_opts);
6166
}
6267

6368

69+
/*
70+
* cluster_conn_opts()
71+
*
72+
* Return standard command-line options for connecting to this cluster when
73+
* using psql, pg_dump, etc. Ideally this would match what get_db_conn()
74+
* sets, but the utilities we need aren't very consistent about the treatment
75+
* of database name options, so we leave that out.
76+
*
77+
* Note result is in static storage, so use it right away.
78+
*/
79+
char *
80+
cluster_conn_opts(ClusterInfo *cluster)
81+
{
82+
static char conn_opts[MAXPGPATH + NAMEDATALEN + 100];
83+
84+
if (cluster->sockdir)
85+
snprintf(conn_opts, sizeof(conn_opts),
86+
"--host \"%s\" --port %d --username \"%s\"",
87+
cluster->sockdir, cluster->port, os_info.user);
88+
else
89+
snprintf(conn_opts, sizeof(conn_opts),
90+
"--port %d --username \"%s\"",
91+
cluster->port, os_info.user);
92+
93+
return conn_opts;
94+
}
95+
96+
6497
/*
6598
* executeQueryOrDie()
6699
*
@@ -140,17 +173,35 @@ stop_postmaster_atexit(void)
140173
void
141174
start_postmaster(ClusterInfo *cluster)
142175
{
143-
char cmd[MAXPGPATH];
176+
char cmd[MAXPGPATH * 4 + 1000];
144177
PGconn *conn;
145178
bool exit_hook_registered = false;
146179
bool pg_ctl_return = false;
180+
char socket_string[MAXPGPATH + 200];
147181

148182
if (!exit_hook_registered)
149183
{
150184
atexit(stop_postmaster_atexit);
151185
exit_hook_registered = true;
152186
}
153187

188+
socket_string[0] = '\0';
189+
190+
#ifdef HAVE_UNIX_SOCKETS
191+
/* prevent TCP/IP connections, restrict socket access */
192+
strcat(socket_string,
193+
" -c listen_addresses='' -c unix_socket_permissions=0700");
194+
195+
/* Have a sockdir? Tell the postmaster. */
196+
if (cluster->sockdir)
197+
snprintf(socket_string + strlen(socket_string),
198+
sizeof(socket_string) - strlen(socket_string),
199+
" -c %s='%s'",
200+
(GET_MAJOR_VERSION(cluster->major_version) < 903) ?
201+
"unix_socket_directory" : "unix_socket_directories",
202+
cluster->sockdir);
203+
#endif
204+
154205
/*
155206
* Using autovacuum=off disables cleanup vacuum and analyze, but freeze
156207
* vacuums can still happen, so we set autovacuum_freeze_max_age to its
@@ -159,12 +210,12 @@ start_postmaster(ClusterInfo *cluster)
159210
* not touch them.
160211
*/
161212
snprintf(cmd, sizeof(cmd),
162-
"\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d %s %s\" start",
213+
"\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d %s %s%s\" start",
163214
cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
164215
(cluster->controldata.cat_ver >=
165216
BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
166217
"-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
167-
cluster->pgopts ? cluster->pgopts : "");
218+
cluster->pgopts ? cluster->pgopts : "", socket_string);
168219

169220
/*
170221
* Don't throw an error right away, let connecting throw the error because

doc/src/sgml/pgupgrade.sgml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,14 @@ psql --username postgres --file script.sql postgres
519519
<literal>-d /real-data-directory -o '-D /configuration-directory'</>.
520520
</para>
521521

522+
<para>
523+
If doing <option>--check</> with a running old server of a pre-9.1 version,
524+
and the old server is using a Unix-domain socket directory that is
525+
different from the default built into the new <productname>PostgreSQL</>
526+
installation, set <envar>PGHOST</> to point to the socket location of the
527+
old server. (This is not relevant on Windows.)
528+
</para>
529+
522530
<para>
523531
A Log-Shipping Standby Server (<xref linkend="warm-standby">) cannot
524532
be upgraded because the server must allow writes. The simplest way

0 commit comments

Comments
 (0)