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

Commit 2fe3bdb

Browse files
committed
Check return value of pclose() correctly
Some callers didn't check the return value of pclose() or ClosePipeStream() correctly. Either they didn't check it at all or they treated it like the return of fclose(). The correct way is to first check whether the return value is -1, and then report errno, and then check the return value like a result from system(), for which we already have wait_result_to_str() to make it simpler. To make this more compact, expand wait_result_to_str() to also handle -1 explicitly. Reviewed-by: Ankit Kumar Pandey <itsankitkp@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/8cd9fb02-bc26-65f1-a809-b1cb360eef73@enterprisedb.com
1 parent b7f3981 commit 2fe3bdb

File tree

8 files changed

+57
-15
lines changed

8 files changed

+57
-15
lines changed

src/backend/commands/collationcmds.c

+10-1
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ pg_import_system_collations(PG_FUNCTION_ARGS)
640640
int naliases,
641641
maxaliases,
642642
i;
643+
int pclose_rc;
643644

644645
/* expansible array of aliases */
645646
maxaliases = 100;
@@ -746,7 +747,15 @@ pg_import_system_collations(PG_FUNCTION_ARGS)
746747
}
747748
}
748749

749-
ClosePipeStream(locale_a_handle);
750+
pclose_rc = ClosePipeStream(locale_a_handle);
751+
if (pclose_rc != 0)
752+
{
753+
ereport(ERROR,
754+
(errcode_for_file_access(),
755+
errmsg("could not execute command \"%s\": %s",
756+
"locale -a",
757+
wait_result_to_str(pclose_rc))));
758+
}
750759

751760
/*
752761
* Before processing the aliases, sort them by locale name. The point

src/bin/pg_ctl/pg_ctl.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -2154,12 +2154,11 @@ adjust_data_dir(void)
21542154
fflush(NULL);
21552155

21562156
fd = popen(cmd, "r");
2157-
if (fd == NULL || fgets(filename, sizeof(filename), fd) == NULL)
2157+
if (fd == NULL || fgets(filename, sizeof(filename), fd) == NULL || pclose(fd) != 0)
21582158
{
21592159
write_stderr(_("%s: could not determine the data directory using command \"%s\"\n"), progname, cmd);
21602160
exit(1);
21612161
}
2162-
pclose(fd);
21632162
free(my_exec_path);
21642163

21652164
/* strip trailing newline and carriage return */

src/bin/pg_upgrade/controldata.c

+9-3
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
7575
uint32 logid = 0;
7676
uint32 segno = 0;
7777
char *resetwal_bin;
78-
78+
int rc;
7979

8080
/*
8181
* Because we test the pg_resetwal output as strings, it has to be in
@@ -170,7 +170,10 @@ get_control_data(ClusterInfo *cluster, bool live_check)
170170
}
171171
}
172172

173-
pclose(output);
173+
rc = pclose(output);
174+
if (rc != 0)
175+
pg_fatal("could not get control data using %s: %s",
176+
cmd, wait_result_to_str(rc));
174177

175178
if (!got_cluster_state)
176179
{
@@ -500,7 +503,10 @@ get_control_data(ClusterInfo *cluster, bool live_check)
500503
}
501504
}
502505

503-
pclose(output);
506+
rc = pclose(output);
507+
if (rc != 0)
508+
pg_fatal("could not get control data using %s: %s",
509+
cmd, wait_result_to_str(rc));
504510

505511
/*
506512
* Restore environment variables. Note all but LANG and LC_MESSAGES were

src/bin/pg_upgrade/exec.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ get_bin_version(ClusterInfo *cluster)
3535
char cmd[MAXPGPATH],
3636
cmd_output[MAX_STRING];
3737
FILE *output;
38+
int rc;
3839
int v1 = 0,
3940
v2 = 0;
4041

@@ -46,7 +47,10 @@ get_bin_version(ClusterInfo *cluster)
4647
pg_fatal("could not get pg_ctl version data using %s: %s",
4748
cmd, strerror(errno));
4849

49-
pclose(output);
50+
rc = pclose(output);
51+
if (rc != 0)
52+
pg_fatal("could not get pg_ctl version data using %s: %s",
53+
cmd, wait_result_to_str(rc));
5054

5155
if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1)
5256
pg_fatal("could not get pg_ctl version output from %s", cmd);

src/bin/pg_upgrade/option.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ adjust_data_dir(ClusterInfo *cluster)
384384
cmd_output[MAX_STRING];
385385
FILE *fp,
386386
*output;
387+
int rc;
387388

388389
/* Initially assume config dir and data dir are the same */
389390
cluster->pgconfig = pg_strdup(cluster->pgdata);
@@ -423,7 +424,10 @@ adjust_data_dir(ClusterInfo *cluster)
423424
pg_fatal("could not get data directory using %s: %s",
424425
cmd, strerror(errno));
425426

426-
pclose(output);
427+
rc = pclose(output);
428+
if (rc != 0)
429+
pg_fatal("could not get control data directory using %s: %s",
430+
cmd, wait_result_to_str(rc));
427431

428432
/* strip trailing newline and carriage return */
429433
(void) pg_strip_crlf(cmd_output);

src/bin/pgbench/pgbench.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3002,7 +3002,7 @@ runShellCommand(Variables *variables, char *variable, char **argv, int argc)
30023002
}
30033003
if (pclose(fp) < 0)
30043004
{
3005-
pg_log_error("%s: could not close shell command", argv[0]);
3005+
pg_log_error("%s: could not run shell command: %m", argv[0]);
30063006
return false;
30073007
}
30083008

src/bin/psql/command.c

+14-4
Original file line numberDiff line numberDiff line change
@@ -2731,14 +2731,24 @@ exec_command_write(PsqlScanState scan_state, bool active_branch,
27312731
fprintf(fd, "%s\n", previous_buf->data);
27322732

27332733
if (is_pipe)
2734+
{
27342735
result = pclose(fd);
2736+
2737+
if (result != 0)
2738+
{
2739+
pg_log_error("%s: %s", fname, wait_result_to_str(result));
2740+
status = PSQL_CMD_ERROR;
2741+
}
2742+
}
27352743
else
2744+
{
27362745
result = fclose(fd);
27372746

2738-
if (result == EOF)
2739-
{
2740-
pg_log_error("%s: %m", fname);
2741-
status = PSQL_CMD_ERROR;
2747+
if (result == EOF)
2748+
{
2749+
pg_log_error("%s: %m", fname);
2750+
status = PSQL_CMD_ERROR;
2751+
}
27422752
}
27432753
}
27442754

src/common/wait_error.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,24 @@
2626
/*
2727
* Return a human-readable string explaining the reason a child process
2828
* terminated. The argument is a return code returned by wait(2) or
29-
* waitpid(2). The result is a translated, palloc'd or malloc'd string.
29+
* waitpid(2), which also applies to pclose(3) and system(3). The result is a
30+
* translated, palloc'd or malloc'd string.
3031
*/
3132
char *
3233
wait_result_to_str(int exitstatus)
3334
{
3435
char str[512];
3536

36-
if (WIFEXITED(exitstatus))
37+
/*
38+
* To simplify using this after pclose() and system(), handle status -1
39+
* first. In that case, there is no wait result but some error indicated
40+
* by errno.
41+
*/
42+
if (exitstatus == -1)
43+
{
44+
snprintf(str, sizeof(str), "%m");
45+
}
46+
else if (WIFEXITED(exitstatus))
3747
{
3848
/*
3949
* Give more specific error message for some common exit codes that

0 commit comments

Comments
 (0)