Fix pgpool child process to obtain process information.
authorTatsuo Ishii <ishii@sraoss.co.jp>
Sat, 9 Apr 2022 06:54:45 +0000 (15:54 +0900)
committerTatsuo Ishii <ishii@sraoss.co.jp>
Sat, 9 Apr 2022 06:54:45 +0000 (15:54 +0900)
ProcesInfo was obtained by using pool_get_process_info(). But this API
is not suitable for child process because:

- does inefficient linear search over all ProcessInfo slots (there are
  num_init_children slots).

- due to race condition the search key pid might not be set or removed
  in the slot. I think it is possible that by the time when child
  process starts execution, the pid is not yet set in the slot in the
  shared memory. Also when child process is killed by parent process,
  it may set pid to 0 before the child process receive kill signal.

So use pool_get_my_process_info() instead of pool_get_process_info().
which just returns the slot by using global variable my_proc_id as a
key and let child process use it.  my_proc_id was set by the parent
process when the child process was spawn.

The call to pool_get_process_info() in child.c was added in v4.3. So
back patch to V4_3_STABLE.

src/protocol/child.c

index e9f84a4e2a0b9ffee1a8b3dab0bf23c5ae8ec4c8..962f1e4c202686a08ef3b920524f70d7104f74e8 100644 (file)
@@ -5,7 +5,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2020     PgPool Global Development Group
+ * Copyright (c) 2003-2022     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -159,8 +159,6 @@ do_child(int *fds)
        ereport(DEBUG2,
                        (errmsg("I am Pgpool Child process with pid: %d", getpid())));
 
-       ProcessInfo* proc_info = pool_get_process_info(getpid());
-
        /* Identify myself via ps */
        init_ps_display("", "", "", "");
 
@@ -283,7 +281,7 @@ do_child(int *fds)
                        if (pool_config->child_max_connections > 0)
                                connections_count++;
 
-                       proc_info->client_connection_count++;
+                       pool_get_my_process_info()->client_connection_count++;
 
                        /* check if maximum connections count for this child reached */
                        if ((pool_config->child_max_connections > 0) &&
@@ -330,10 +328,10 @@ do_child(int *fds)
                pool_session_context_destroy();
 
                front_end_fd = wait_for_new_connections(fds, &saddr);
-               proc_info->wait_for_connect = 0;
+               pool_get_my_process_info()->wait_for_connect = 0;
                if (front_end_fd == OPERATION_TIMEOUT)
                {
-                       if (pool_config->child_life_time > 0 && proc_info->connected)
+                       if (pool_config->child_life_time > 0 && pool_get_my_process_info()->connected)
                        {
                                ereport(DEBUG1,
                                                (errmsg("child life %d seconds expired", pool_config->child_life_time)));
@@ -404,7 +402,7 @@ do_child(int *fds)
                        child_frontend = NULL;
                        continue;
                }
-               proc_info->connected = 1;
+               pool_get_my_process_info()->connected = 1;
 
                /*
                 * show ps status
@@ -469,7 +467,7 @@ do_child(int *fds)
                if (pool_config->child_max_connections > 0)
                        connections_count++;
 
-               proc_info->client_connection_count++;
+               pool_get_my_process_info()->client_connection_count++;
 
                /* check if maximum connections count for this child reached */
                if ((pool_config->child_max_connections > 0) &&
@@ -1479,8 +1477,6 @@ wait_for_new_connections(int *fds, SockAddr *saddr)
        struct timeval *timeout;
        struct timeval timeoutdata;
 
-       ProcessInfo* proc_info = pool_get_process_info(getpid());
-
        for (walk = fds; *walk != -1; walk++)
                socket_set_nonblock(*walk);
 
@@ -1575,9 +1571,9 @@ wait_for_new_connections(int *fds, SockAddr *saddr)
                        break;
 
                /* timeout */
-               proc_info->wait_for_connect++;
+               pool_get_my_process_info()->wait_for_connect++;
 
-               if (proc_info->wait_for_connect > pool_config->child_life_time)
+               if (pool_get_my_process_info()->wait_for_connect > pool_config->child_life_time)
                        return OPERATION_TIMEOUT;
 
        }
@@ -2113,6 +2109,5 @@ static int opt_sort(const void *a, const void *b)
 void
 set_process_status(ProcessStatus status)
 {
-       ProcessInfo* proc_info = pool_get_process_info(getpid());
-       proc_info->status = status;
+       pool_get_my_process_info()->status = status;
 }