Get rid of a bunch of dubious error handling code in pgbench by just erroring
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 12 Aug 2010 21:10:59 +0000 (21:10 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 12 Aug 2010 21:10:59 +0000 (21:10 +0000)
out immediately on any out-of-memory condition.  It's rather pointless to
imagine that pgbench will be able to continue usefully after a malloc
failure, and in any case there were a number of unchecked mallocs.

contrib/pgbench/pgbench.c

index 88d7e524694304321168dbc4e5b00f54d52ec41a..27ea731f3cfa01dda4684ae2a6d1c56c9838cd7d 100644 (file)
@@ -4,7 +4,7 @@
  * A simple benchmark program for PostgreSQL
  * Originally written by Tatsuo Ishii and enhanced by many contributors.
  *
- * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.100 2010/08/12 20:39:39 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.101 2010/08/12 21:10:59 tgl Exp $
  * Copyright (c) 2000-2010, PostgreSQL Global Development Group
  * ALL RIGHTS RESERVED;
  *
@@ -277,6 +277,53 @@ static char *select_only = {
 static void setalarm(int seconds);
 static void *threadRun(void *arg);
 
+
+/*
+ * routines to check mem allocations and fail noisily.
+ */
+static void *
+xmalloc(size_t size)
+{
+   void       *result;
+
+   result = malloc(size);
+   if (!result)
+   {
+       fprintf(stderr, "out of memory\n");
+       exit(1);
+   }
+   return result;
+}
+
+static void *
+xrealloc(void *ptr, size_t size)
+{
+   void       *result;
+
+   result = realloc(ptr, size);
+   if (!result)
+   {
+       fprintf(stderr, "out of memory\n");
+       exit(1);
+   }
+   return result;
+}
+
+static char *
+xstrdup(const char *s)
+{
+   char       *result;
+
+   result = strdup(s);
+   if (!result)
+   {
+       fprintf(stderr, "out of memory\n");
+       exit(1);
+   }
+   return result;
+}
+
+
 static void
 usage(const char *progname)
 {
@@ -480,28 +527,17 @@ putVariable(CState *st, const char *context, char *name, char *value)
        }
 
        if (st->variables)
-           newvars = (Variable *) realloc(st->variables,
+           newvars = (Variable *) xrealloc(st->variables,
                                    (st->nvariables + 1) * sizeof(Variable));
        else
-           newvars = (Variable *) malloc(sizeof(Variable));
-
-       if (newvars == NULL)
-           goto out_of_memory;
+           newvars = (Variable *) xmalloc(sizeof(Variable));
 
        st->variables = newvars;
 
        var = &newvars[st->nvariables];
 
-       var->name = NULL;
-       var->value = NULL;
-
-       if ((var->name = strdup(name)) == NULL ||
-           (var->value = strdup(value)) == NULL)
-       {
-           free(var->name);
-           free(var->value);
-           return false;
-       }
+       var->name = xstrdup(name);
+       var->value = xstrdup(value);
 
        st->nvariables++;
 
@@ -512,18 +548,14 @@ putVariable(CState *st, const char *context, char *name, char *value)
    {
        char       *val;
 
-       if ((val = strdup(value)) == NULL)
-           return false;
+       /* dup then free, in case value is pointing at this variable */
+       val = xstrdup(value);
 
        free(var->value);
        var->value = val;
    }
 
    return true;
-
-out_of_memory:
-   fprintf(stderr, "%s: out of memory for variable '%s'\n", context, name);
-   return false;
 }
 
 static char *
@@ -539,9 +571,7 @@ parseVariable(const char *sql, int *eaten)
    if (i == 1)
        return NULL;
 
-   name = malloc(i);
-   if (name == NULL)
-       return NULL;
+   name = xmalloc(i);
    memcpy(name, &sql[1], i - 1);
    name[i - 1] = '\0';
 
@@ -556,16 +586,9 @@ replaceVariable(char **sql, char *param, int len, char *value)
 
    if (valueln > len)
    {
-       char       *tmp;
        size_t      offset = param - *sql;
 
-       tmp = realloc(*sql, strlen(*sql) - len + valueln + 1);
-       if (tmp == NULL)
-       {
-           free(*sql);
-           return NULL;
-       }
-       *sql = tmp;
+       *sql = xrealloc(*sql, strlen(*sql) - len + valueln + 1);
        param = *sql + offset;
    }
 
@@ -606,8 +629,7 @@ assignVariables(CState *st, char *sql)
            continue;
        }
 
-       if ((p = replaceVariable(&sql, p, eaten, val)) == NULL)
-           return NULL;
+       p = replaceVariable(&sql, p, eaten, val);
    }
 
    return sql;
@@ -902,13 +924,8 @@ top:
        {
            char       *sql;
 
-           if ((sql = strdup(command->argv[0])) == NULL
-               || (sql = assignVariables(st, sql)) == NULL)
-           {
-               fprintf(stderr, "out of memory\n");
-               st->ecnt++;
-               return true;
-           }
+           sql = xstrdup(command->argv[0]);
+           sql = assignVariables(st, sql);
 
            if (debug)
                fprintf(stderr, "client %d sending %s\n", st->id, sql);
@@ -1345,9 +1362,7 @@ parseQuery(Command *cmd, const char *raw_sql)
    char       *sql,
               *p;
 
-   sql = strdup(raw_sql);
-   if (sql == NULL)
-       return false;
+   sql = xstrdup(raw_sql);
    cmd->argc = 1;
 
    p = sql;
@@ -1374,8 +1389,7 @@ parseQuery(Command *cmd, const char *raw_sql)
        }
 
        sprintf(var, "$%d", cmd->argc);
-       if ((p = replaceVariable(&sql, p, eaten, var)) == NULL)
-           return false;
+       p = replaceVariable(&sql, p, eaten, var);
 
        cmd->argv[cmd->argc] = name;
        cmd->argc++;
@@ -1410,12 +1424,8 @@ process_commands(char *buf)
        return NULL;
 
    /* Allocate and initialize Command structure */
-   my_commands = (Command *) malloc(sizeof(Command));
-   if (my_commands == NULL)
-       return NULL;
-   my_commands->line = strdup(buf);
-   if (my_commands->line == NULL)
-       return NULL;
+   my_commands = (Command *) xmalloc(sizeof(Command));
+   my_commands->line = xstrdup(buf);
    my_commands->command_num = num_commands++;
    my_commands->type = 0;      /* until set */
    my_commands->argc = 0;
@@ -1429,12 +1439,8 @@ process_commands(char *buf)
 
        while (tok != NULL)
        {
-           if ((my_commands->argv[j] = strdup(tok)) == NULL)
-               return NULL;
-
+           my_commands->argv[j++] = xstrdup(tok);
            my_commands->argc++;
-
-           j++;
            tok = strtok(NULL, delim);
        }
 
@@ -1443,7 +1449,7 @@ process_commands(char *buf)
            if (my_commands->argc < 4)
            {
                fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]);
-               return NULL;
+               exit(1);
            }
 
            for (j = 4; j < my_commands->argc; j++)
@@ -1455,7 +1461,7 @@ process_commands(char *buf)
            if (my_commands->argc < 3)
            {
                fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]);
-               return NULL;
+               exit(1);
            }
 
            for (j = my_commands->argc < 5 ? 3 : 5; j < my_commands->argc; j++)
@@ -1467,7 +1473,7 @@ process_commands(char *buf)
            if (my_commands->argc < 2)
            {
                fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]);
-               return NULL;
+               exit(1);
            }
 
            /*
@@ -1498,7 +1504,7 @@ process_commands(char *buf)
                {
                    fprintf(stderr, "%s: unknown time unit '%s' - must be us, ms or s\n",
                            my_commands->argv[0], my_commands->argv[2]);
-                   return NULL;
+                   exit(1);
                }
            }
 
@@ -1511,7 +1517,7 @@ process_commands(char *buf)
            if (my_commands->argc < 3)
            {
                fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]);
-               return NULL;
+               exit(1);
            }
        }
        else if (pg_strcasecmp(my_commands->argv[0], "shell") == 0)
@@ -1519,13 +1525,13 @@ process_commands(char *buf)
            if (my_commands->argc < 1)
            {
                fprintf(stderr, "%s: missing command\n", my_commands->argv[0]);
-               return NULL;
+               exit(1);
            }
        }
        else
        {
            fprintf(stderr, "Invalid command %s\n", my_commands->argv[0]);
-           return NULL;
+           exit(1);
        }
    }
    else
@@ -1535,17 +1541,16 @@ process_commands(char *buf)
        switch (querymode)
        {
            case QUERY_SIMPLE:
-               if ((my_commands->argv[0] = strdup(p)) == NULL)
-                   return NULL;
+               my_commands->argv[0] = xstrdup(p);
                my_commands->argc++;
                break;
            case QUERY_EXTENDED:
            case QUERY_PREPARED:
                if (!parseQuery(my_commands, p))
-                   return NULL;
+                   exit(1);
                break;
            default:
-               return NULL;
+               exit(1);
        }
    }
 
@@ -1570,9 +1575,7 @@ process_file(char *filename)
    }
 
    alloc_num = COMMANDS_ALLOC_NUM;
-   my_commands = (Command **) malloc(sizeof(Command *) * alloc_num);
-   if (my_commands == NULL)
-       return false;
+   my_commands = (Command **) xmalloc(sizeof(Command *) * alloc_num);
 
    if (strcmp(filename, "-") == 0)
        fd = stdin;
@@ -1598,12 +1601,7 @@ process_file(char *filename)
        if (lineno >= alloc_num)
        {
            alloc_num += COMMANDS_ALLOC_NUM;
-           my_commands = realloc(my_commands, sizeof(Command *) * alloc_num);
-           if (my_commands == NULL)
-           {
-               fclose(fd);
-               return false;
-           }
+           my_commands = xrealloc(my_commands, sizeof(Command *) * alloc_num);
        }
    }
    fclose(fd);
@@ -1625,13 +1623,8 @@ process_builtin(char *tb)
    char        buf[BUFSIZ];
    int         alloc_num;
 
-   if (*tb == '\0')
-       return NULL;
-
    alloc_num = COMMANDS_ALLOC_NUM;
-   my_commands = (Command **) malloc(sizeof(Command *) * alloc_num);
-   if (my_commands == NULL)
-       return NULL;
+   my_commands = (Command **) xmalloc(sizeof(Command *) * alloc_num);
 
    lineno = 0;
 
@@ -1662,11 +1655,7 @@ process_builtin(char *tb)
        if (lineno >= alloc_num)
        {
            alloc_num += COMMANDS_ALLOC_NUM;
-           my_commands = realloc(my_commands, sizeof(Command *) * alloc_num);
-           if (my_commands == NULL)
-           {
-               return NULL;
-           }
+           my_commands = xrealloc(my_commands, sizeof(Command *) * alloc_num);
        }
    }
 
@@ -1831,14 +1820,8 @@ main(int argc, char **argv)
    else if ((env = getenv("PGUSER")) != NULL && *env != '\0')
        login = env;
 
-   state = (CState *) malloc(sizeof(CState));
-   if (state == NULL)
-   {
-       fprintf(stderr, "Couldn't allocate memory for state\n");
-       exit(1);
-   }
-
-   memset(state, 0, sizeof(*state));
+   state = (CState *) xmalloc(sizeof(CState));
+   memset(state, 0, sizeof(CState));
 
    while ((c = getopt(argc, argv, "ih:nvp:dSNc:j:Crs:t:T:U:lf:D:F:M:")) != -1)
    {
@@ -2051,14 +2034,8 @@ main(int argc, char **argv)
 
    if (nclients > 1)
    {
-       state = (CState *) realloc(state, sizeof(CState) * nclients);
-       if (state == NULL)
-       {
-           fprintf(stderr, "Couldn't allocate memory for state\n");
-           exit(1);
-       }
-
-       memset(state + 1, 0, sizeof(*state) * (nclients - 1));
+       state = (CState *) xrealloc(state, sizeof(CState) * nclients);
+       memset(state + 1, 0, sizeof(CState) * (nclients - 1));
 
        /* copy any -D switch values to all clients */
        for (i = 1; i < nclients; i++)
@@ -2181,7 +2158,7 @@ main(int argc, char **argv)
    }
 
    /* set up thread data structures */
-   threads = (TState *) malloc(sizeof(TState) * nthreads);
+   threads = (TState *) xmalloc(sizeof(TState) * nthreads);
    for (i = 0; i < nthreads; i++)
    {
        TState *thread = &threads[i];
@@ -2196,9 +2173,9 @@ main(int argc, char **argv)
            int     t;
 
            thread->exec_elapsed = (instr_time *)
-               malloc(sizeof(instr_time) * num_commands);
+               xmalloc(sizeof(instr_time) * num_commands);
            thread->exec_count = (int *)
-               malloc(sizeof(int) * num_commands);
+               xmalloc(sizeof(int) * num_commands);
 
            for (t = 0; t < num_commands; t++)
            {
@@ -2289,7 +2266,7 @@ threadRun(void *arg)
    int         remains = nstate;       /* number of remaining clients */
    int         i;
 
-   result = malloc(sizeof(TResult));
+   result = xmalloc(sizeof(TResult));
    INSTR_TIME_SET_ZERO(result->conn_time);
 
    /* open log file if requested */
@@ -2503,8 +2480,12 @@ pthread_create(pthread_t *thread,
    void       *ret;
    instr_time  start_time;
 
-   th = (fork_pthread *) malloc(sizeof(fork_pthread));
-   pipe(th->pipes);
+   th = (fork_pthread *) xmalloc(sizeof(fork_pthread));
+   if (pipe(th->pipes) < 0)
+   {
+       free(th);
+       return errno;
+   }
 
    th->pid = fork();
    if (th->pid == -1)          /* error */
@@ -2558,7 +2539,7 @@ pthread_join(pthread_t th, void **thread_return)
    if (thread_return != NULL)
    {
        /* assume result is TResult */
-       *thread_return = malloc(sizeof(TResult));
+       *thread_return = xmalloc(sizeof(TResult));
        if (read(th->pipes[0], *thread_return, sizeof(TResult)) != sizeof(TResult))
        {
            free(*thread_return);
@@ -2626,7 +2607,7 @@ pthread_create(pthread_t *thread,
    int         save_errno;
    win32_pthread *th;
 
-   th = (win32_pthread *) malloc(sizeof(win32_pthread));
+   th = (win32_pthread *) xmalloc(sizeof(win32_pthread));
    th->routine = start_routine;
    th->arg = arg;
    th->result = NULL;