Make time calculations always long long.
authorTatsuo Ishii <ishii@postgresql.org>
Fri, 3 Oct 2025 12:10:50 +0000 (21:10 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Thu, 9 Oct 2025 10:40:08 +0000 (19:40 +0900)
Previously pgpool assumed that time_t to be a simple long. This causes
a lot of compile time warnings on certain systems, for example
OpenBSD because on the system time_t is __int64, which results in long
long. This commit upcasts such calculations to long long to avoid the
issue.

This way times can't get truncated and for the places where time_t is
actually used as a time and not a time diff this would allow pgpool to
keep working correctly post Y2038 on 64 bit clean time_t systems
(e.g. i386 OpenBSD).

Moreover, json_get_long_value_for_key is changed to
json_get_llong_value_for_key and changed the parameter to long long.
This makes it more in line _json_value's integer, which is defined as
int64. This should also give 32 bit platforms proper retrieval of the
max value of an integer and may or may not solve some weird integer
overflow issues.

Backpatch for 4.6 was rebased by Gyorgy Sarvari.

Author: Martijn van Duren <pgpool@list.imperialat.at>
Reviewed-by: Tatsuo Ishii <ishii@postgresql.org>
Reviewed-by: Gyorgy Sarvari <skandigraun@gmail.com>
Backpatch-through: v4.6
Discussion: https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004584.html
Discussion: https://www.postgresql.org/message-id/20251003.211957.2067537305399895611.ishii%40postgresql.org
Discussion: https://github.com/pgpool/pgpool2/pull/128

14 files changed:
src/include/utils/json.h
src/include/watchdog/wd_commands.h
src/include/watchdog/wd_json_data.h
src/main/pgpool_logger.c
src/pcp_con/pcp_worker.c
src/protocol/pool_connection_pool.c
src/query_cache/pool_memqcache.c
src/utils/json.c
src/utils/pool_process_reporting.c
src/utils/pool_relcache.c
src/watchdog/watchdog.c
src/watchdog/wd_commands.c
src/watchdog/wd_heartbeat.c
src/watchdog/wd_json_data.c

index cb4378a9c1251f9561b0bb7b522c5ce0d5c7f7d6..ad9735e32bce10423af18b89b5472b618e021c53 100644 (file)
@@ -313,7 +313,7 @@ extern "C"
 /* pgpool-II extensions */
 json_value *json_get_value_for_key(json_value *source, const char *key);
 int                    json_get_int_value_for_key(json_value *source, const char *key, int *value);
-int                    json_get_long_value_for_key(json_value *source, const char *key, long *value);
+int                    json_get_llong_value_for_key(json_value * source, const char *key, long long *value);
 char      *json_get_string_value_for_key(json_value *source, const char *key);
 int                    json_get_bool_value_for_key(json_value *source, const char *key, bool *value);
 
index 61326137de98f397af489422a3a160e7de6ced88..a016772f6ebe79083a8d1fd424667b878b810103 100644 (file)
@@ -52,7 +52,7 @@ typedef struct WDGenericData
                char       *stringVal;
                int                     intVal;
                bool            boolVal;
-               long            longVal;
+               long long       longVal;
        }                       data;
 } WDGenericData;
 
index 1016dcae8491060a270ea2b7a6ec373b437a5624..01e40e78415a12b1a2901178ddf15477945f9248 100644 (file)
@@ -51,8 +51,8 @@ extern bool parse_node_status_json(char *json_data, int data_len, int *nodeID, i
 
 
 extern bool parse_beacon_message_json(char *json_data, int data_len, int *state,
-                                                                         long *seconds_since_node_startup,
-                                                                         long *seconds_since_current_state,
+                                                                         long long *seconds_since_node_startup,
+                                                                         long long *seconds_since_current_state,
                                                                          int *quorumStatus,
                                                                          int *standbyNodesCount,
                                                                          bool *escalated);
index 89980c95bf47b9e3dddefd4b2e3a80f2927cd593..d57a0d0006b56452b7e2d53e3e2a4083de2b7e1e 100644 (file)
@@ -50,7 +50,7 @@
 #include "main/pgpool_logger.h"
 
 #define DEVNULL "/dev/null"
-typedef int64 pg_time_t;
+typedef time_t pg_time_t;
 
 /*
  * We read() into a temp buffer twice as big as a chunk, so that any fragment
index a9d02e0119b89f382f65e382f4dcd082eb0fcfb3..6c95f98e4536ddec16ee0180e95d04a2d2cf1272 100644 (file)
@@ -933,9 +933,9 @@ inform_node_info(PCP_CONNECTION *frontend, char *buf)
 
                        snprintf(standby_delay_by_time_str, sizeof(standby_delay_by_time_str), "%d", bi->standby_delay_by_time);
 
-                       snprintf(standby_delay_str, sizeof(standby_delay_str), UINT64_FORMAT, bi->standby_delay);
+                       snprintf(standby_delay_str, sizeof(standby_delay_str), "%lld", (long long)bi->standby_delay);
 
-                       snprintf(status_changed_time_str, sizeof(status_changed_time_str), UINT64_FORMAT, bi->status_changed_time);
+                       snprintf(status_changed_time_str, sizeof(status_changed_time_str), "%lld", (long long)bi->status_changed_time);
 
                        pcp_write(frontend, "i", 1);
                        wsize = htonl(sizeof(code) +
index c3b369dc25a51059e262aeb82a6ea9fca4ca1f21..97ded29f389802d714dfad40b7faf40be5e9d2ed 100644 (file)
@@ -302,10 +302,10 @@ pool_create_cp(void)
 
                ereport(DEBUG1,
                                (errmsg("creating connection pool"),
-                                errdetail("user: %s database: %s closetime: %ld",
+                                errdetail("user: %s database: %s closetime: %lld",
                                                   CONNECTION_SLOT(p, main_node_id)->sp->user,
                                                   CONNECTION_SLOT(p, main_node_id)->sp->database,
-                                                  CONNECTION_SLOT(p, main_node_id)->closetime)));
+                                                  (long long)CONNECTION_SLOT(p, main_node_id)->closetime)));
 
                if (CONNECTION_SLOT(p, main_node_id)->closetime < closetime)
                {
@@ -366,7 +366,7 @@ pool_connection_pool_timer(POOL_CONNECTION_POOL *backend)
 
        ereport(DEBUG1,
                        (errmsg("setting backend connection close timer"),
-                        errdetail("close time %ld", time(NULL))));
+                        errdetail("close time %lld", (long long)time(NULL))));
 
        /* Set connection close time */
        for (i = 0; i < NUM_BACKENDS; i++)
@@ -424,7 +424,7 @@ pool_backend_timer(void)
        now = time(NULL);
 
        ereport(DEBUG1,
-                       (errmsg("backend timer handler called at %ld", now)));
+                       (errmsg("backend timer handler called at %lld", (long long)now)));
 
        for (i = 0; i < pool_config->max_pool; i++, p++)
        {
@@ -442,8 +442,8 @@ pool_backend_timer(void)
 
                        ereport(DEBUG1,
                                        (errmsg("backend timer handler called"),
-                                        errdetail("expire time: %ld",
-                                                          MAIN_CONNECTION(p)->closetime + pool_config->connection_life_time)));
+                                        errdetail("expire time: %lld",
+                                                          (long long)(MAIN_CONNECTION(p)->closetime + pool_config->connection_life_time))));
 
                        if (now >= (MAIN_CONNECTION(p)->closetime + pool_config->connection_life_time))
                        {
index 088ad051adab47afc3bc2b0827211b55dc2302eb..dc2ce911e0afb36ab5b25533a98aa743b2e58445 100644 (file)
@@ -280,7 +280,7 @@ pool_commit_cache(POOL_CONNECTION_POOL *backend, char *query, char *data, size_t
        memqcache_expire = pool_config->memqcache_expire;
        ereport(DEBUG1,
                        (errmsg("committing SELECT results to cache storage"),
-                        errdetail("memqcache_expire = %ld", memqcache_expire)));
+                        errdetail("memqcache_expire = %lld", (long long)memqcache_expire)));
 
        if (pool_is_shmem_cache())
        {
@@ -390,7 +390,7 @@ pool_catalog_commit_cache(POOL_CONNECTION_POOL *backend, char *query, char *data
        memqcache_expire = pool_config->relcache_expire;
        ereport(DEBUG1,
                        (errmsg("committing relation cache to cache storage"),
-                        errdetail("memqcache_expire = %ld", memqcache_expire)));
+                        errdetail("memqcache_expire = %lld", (long long)memqcache_expire)));
 
        if (pool_is_shmem_cache())
        {
@@ -2902,8 +2902,8 @@ pool_find_item_on_shmem_cache(POOL_QUERY_HASH *query_hash)
                        {
                                ereport(DEBUG1,
                                                (errmsg("memcache finding item"),
-                                                errdetail("cache expired: now: %ld timestamp: %ld",
-                                                                  now, cih->timestamp + cih->expire)));
+                                                errdetail("cache expired: now: %lld timestamp: %lld",
+                                                                  (long long)now, (long long)(cih->timestamp + cih->expire))));
                                pool_delete_item_shmem_cache(c);
                                return NULL;
                        }
index 8d156439cfab1a83ddfefb057ecba797c49297f9..9c46298617b0d7ee54f0559a5493cef853b5c450 100644 (file)
@@ -1191,7 +1191,7 @@ json_get_int_value_for_key(json_value *source, const char *key, int *value)
 }
 
 int
-json_get_long_value_for_key(json_value *source, const char *key, long *value)
+json_get_llong_value_for_key(json_value * source, const char *key, long long *value)
 {
        json_value *jNode;
 
index 8e41ccafd5d278af034146084d17a7912b04af09..99c0cc006e6ba9f33423fe21fdb2f05be2c2aab7 100644 (file)
@@ -2071,7 +2071,7 @@ get_health_check_stats(int *nrows)
 
                /* status last changed */
                t = bi->status_changed_time;
-               ereport(LOG, (errmsg("status_changed_time %ld", t)));
+               ereport(LOG,(errmsg("status_changed_time %lld", (long long)t)));
                strftime(stats[i].last_status_change, POOLCONFIG_MAXDATELEN, "%F %T", localtime(&t));
 
                snprintf(stats[i].total_count, POOLCONFIG_MAXLONGCOUNTLEN, UINT64_FORMAT, health_check_stats[i].total_count);
index 2ffe970e9a8574b9334711fddb64261d83b66e10..ca19c0d29cdba4c939cd6e8a7081fca7c3773199 100644 (file)
@@ -187,7 +187,7 @@ pool_search_relcache(POOL_RELCACHE *relcache, POOL_CONNECTION_POOL *backend, cha
                                {
                                        ereport(DEBUG1,
                                                        (errmsg("searching relcache"),
-                                                        errdetail("relcache for database:%s table:%s expired. now:%ld expiration time:%ld", dbname, table, now, relcache->cache[i].expire)));
+                                                        errdetail("relcache for database:%s table:%s expired. now:%lld expiration time:%lld", dbname, table, (long long)now, (long long)relcache->cache[i].expire)));
 
                                        relcache->cache[i].refcnt = 0;
                                        break;
index c37984331541d61aeb051ab81341bb06e32ce772..48d05b1f8bcec772a46a52ecb0628e29b3b98bff 100644 (file)
@@ -6763,8 +6763,8 @@ watchdog_state_machine_nw_isolation(WD_EVENTS event, WatchdogNode *wdNode, WDPac
 static bool
 beacon_message_received_from_node(WatchdogNode *wdNode, WDPacketData *pkt)
 {
-       long            seconds_since_node_startup;
-       long            seconds_since_current_state;
+       long long       seconds_since_node_startup;
+       long long       seconds_since_current_state;
        int                     quorum_status;
        int                     standby_nodes_count;
        bool            escalated;
index 1539ef6753f70694276c15493ad2b38490f123c4..4b313e6c7495ee1b9d54cf626f3769bfb226c108 100644 (file)
@@ -193,9 +193,9 @@ get_wd_runtime_variable_value(char *wd_authkey, char *varName)
 
                        case VALUE_DATA_TYPE_LONG:
                                {
-                                       long            longVal;
+                                       long long       longVal;
 
-                                       if (json_get_long_value_for_key(root, WD_JSON_KEY_VALUE_DATA, &longVal))
+                                       if (json_get_llong_value_for_key(root, WD_JSON_KEY_VALUE_DATA, &longVal))
                                        {
                                                ereport(WARNING,
                                                                (errmsg("get runtime variable value from watchdog failed"),
index 5d08abec0246454e5cb6013bdcca6bf86ef5cff4..8de160ed3c766c60996c027fd4850ed8e32c8ef5 100644 (file)
@@ -850,8 +850,8 @@ packet_to_string_hb(WdHbPacket *pkt, char *str, int maxlen)
 {
        int                     len;
 
-       len = snprintf(str, maxlen, "tv_sec=%ld tv_usec=%ld from=%s",
-                                  pkt->send_time.tv_sec, pkt->send_time.tv_usec, pkt->from);
+       len = snprintf(str, maxlen, "tv_sec=%lld tv_usec=%lld from=%s",
+                                  (long long)pkt->send_time.tv_sec, (long long)pkt->send_time.tv_usec, pkt->from);
 
        return len;
 }
index d5741b3e708438b07e8ae2f45063fcf47963fce8..91dd26a867f7a1195da7ac8950ee752f414e0e27 100644 (file)
@@ -533,6 +533,7 @@ get_watchdog_node_from_json(char *json_data, int data_len, char **authkey)
 {
        json_value *root = NULL;
        char       *ptr;
+       long long       longVal;
        WatchdogNode *wdNode = palloc0(sizeof(WatchdogNode));
 
        root = json_parse(json_data, data_len);
@@ -540,19 +541,20 @@ get_watchdog_node_from_json(char *json_data, int data_len, char **authkey)
        if (root == NULL || root->type != json_object)
                goto ERROR_EXIT;
 
-       if (json_get_long_value_for_key(root, "StartupTimeSecs", &wdNode->startup_time.tv_sec))
+       if (json_get_llong_value_for_key(root, "StartupTimeSecs", &longVal))
        {
                bool            escalated;
-               long            seconds_since_node_startup;
-               long            seconds_since_current_state;
+               long long       seconds_since_node_startup;
+               long long       seconds_since_current_state;
                struct timeval current_time;
 
+               wdNode->startup_time.tv_sec = longVal;
                gettimeofday(&current_time, NULL);
 
                /* The new version does not have StartupTimeSecs Key */
-               if (json_get_long_value_for_key(root, "SecondsSinceStartup", &seconds_since_node_startup))
+               if (json_get_llong_value_for_key(root, "SecondsSinceStartup", &seconds_since_node_startup))
                        goto ERROR_EXIT;
-               if (json_get_long_value_for_key(root, "SecondsSinceCurrentState", &seconds_since_current_state))
+               if (json_get_llong_value_for_key(root, "SecondsSinceCurrentState", &seconds_since_current_state))
                        goto ERROR_EXIT;
                if (json_get_bool_value_for_key(root, "Escalated", &escalated))
                        goto ERROR_EXIT;
@@ -643,8 +645,8 @@ ERROR_EXIT:
 bool
 parse_beacon_message_json(char *json_data, int data_len,
                                                  int *state,
-                                                 long *seconds_since_node_startup,
-                                                 long *seconds_since_current_state,
+                                                 long long *seconds_since_node_startup,
+                                                 long long *seconds_since_current_state,
                                                  int *quorumStatus,
                                                  int *standbyNodesCount,
                                                  bool *escalated)
@@ -658,9 +660,9 @@ parse_beacon_message_json(char *json_data, int data_len,
 
        if (json_get_int_value_for_key(root, "State", state))
                goto ERROR_EXIT;
-       if (json_get_long_value_for_key(root, "SecondsSinceStartup", seconds_since_node_startup))
+       if (json_get_llong_value_for_key(root, "SecondsSinceStartup", seconds_since_node_startup))
                goto ERROR_EXIT;
-       if (json_get_long_value_for_key(root, "SecondsSinceCurrentState", seconds_since_current_state))
+       if (json_get_llong_value_for_key(root, "SecondsSinceCurrentState", seconds_since_current_state))
                goto ERROR_EXIT;
        if (json_get_bool_value_for_key(root, "Escalated", escalated))
                goto ERROR_EXIT;