commit 726c9e87c1e75e5c60b1bfa95441b775438cc87f Author: Muhammad Usama Date: Mon Dec 14 15:41:37 2020 +0500 Use single shared memory segment for all shared variables in Pgpool parent process Shared memory segments is a limited resource and opening too many segments should be avoided. Also the default limit for on some operating systems like OS/X (kern.sysv.shmmni: 32) is very small that you have to increase shmmni just to run Pgpool-II.  So to avoid creating too many shared memory segments, the commit creates a single shared memory segment big enough to hold all required shared memory and put all shared memory variables within that segment one after the other. diff --git a/src/config/pool_config.c b/src/config/pool_config.c index 112c0f57..2286f61e 100644 --- a/src/config/pool_config.c +++ b/src/config/pool_config.c @@ -8,7 +8,7 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 37 +#define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif @@ -46,6 +46,7 @@ typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; +typedef uint64_t flex_uint64_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; @@ -53,6 +54,7 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -83,8 +85,6 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif -#endif /* ! C99 */ - #endif /* ! FLEXINT_H */ #ifdef __cplusplus @@ -332,7 +332,7 @@ void yyfree (void * ); /* Begin user sect3 */ -#define yywrap() 1 +#define yywrap(n) 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; @@ -358,7 +358,7 @@ static void yy_fatal_error (yyconst char msg[] ); */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ - yyleng = (size_t) (yy_cp - yy_bp); \ + yyleng = (yy_size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; @@ -641,7 +641,7 @@ static int input (void ); /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ -#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#define ECHO fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, @@ -652,7 +652,7 @@ static int input (void ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - size_t n; \ + yy_size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -1069,7 +1069,7 @@ static int yy_get_next_buffer (void) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); @@ -1202,7 +1202,7 @@ static int yy_get_next_buffer (void) yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 39); - return yy_is_jam ? 0 : yy_current_state; + return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_INPUT @@ -1253,7 +1253,7 @@ static int yy_get_next_buffer (void) case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) - return EOF; + return 0; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; @@ -1593,8 +1593,8 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ @@ -1602,8 +1602,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len { YY_BUFFER_STATE b; char *buf; - yy_size_t n; - yy_size_t i; + yy_size_t n, i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; @@ -1841,12 +1840,7 @@ int pool_init_config(void) { memset(pool_config, 0, sizeof(POOL_CONFIG)); -#ifndef POOL_PRIVATE - g_pool_config.backend_desc = pool_shared_memory_create(sizeof(BackendDesc)); - memset(g_pool_config.backend_desc, 0, sizeof(BackendDesc)); -#else g_pool_config.backend_desc = palloc0(sizeof(BackendDesc)); -#endif g_pool_config.health_check_params = palloc0(MAX_NUM_BACKENDS*sizeof(HealthCheckParams)); InitializeConfigOptions(); diff --git a/src/config/pool_config.l b/src/config/pool_config.l index f9a502d3..68fc5fc1 100644 --- a/src/config/pool_config.l +++ b/src/config/pool_config.l @@ -110,12 +110,7 @@ int pool_init_config(void) { memset(pool_config, 0, sizeof(POOL_CONFIG)); -#ifndef POOL_PRIVATE - g_pool_config.backend_desc = pool_shared_memory_create(sizeof(BackendDesc)); - memset(g_pool_config.backend_desc, 0, sizeof(BackendDesc)); -#else g_pool_config.backend_desc = palloc0(sizeof(BackendDesc)); -#endif g_pool_config.health_check_params = palloc0(MAX_NUM_BACKENDS*sizeof(HealthCheckParams)); InitializeConfigOptions(); diff --git a/src/include/pool.h b/src/include/pool.h index 848f1b98..23599eb3 100644 --- a/src/include/pool.h +++ b/src/include/pool.h @@ -607,6 +607,8 @@ extern int get_frontend_protocol_version(void); /*pool_shmem.c*/ extern void *pool_shared_memory_create(size_t size); extern void pool_shmem_exit(int code); +extern void initialize_shared_memory_main_segment(size_t size); +extern void * pool_shared_memory_segment_get_chunk(size_t size); /* pool_main.c*/ diff --git a/src/include/query_cache/pool_memqcache.h b/src/include/query_cache/pool_memqcache.h index 971e6317..d1df1d8a 100644 --- a/src/include/query_cache/pool_memqcache.h +++ b/src/include/query_cache/pool_memqcache.h @@ -230,6 +230,7 @@ typedef struct } POOL_HASH_HEADER; extern int pool_hash_init(int nelements); +extern size_t pool_hash_size(int nelements); extern POOL_CACHEID * pool_hash_search(POOL_QUERY_HASH * key); extern int pool_hash_delete(POOL_QUERY_HASH * key); extern uint32 hash_any(unsigned char *k, int keylen); diff --git a/src/include/watchdog/wd_internal_commands.h b/src/include/watchdog/wd_internal_commands.h index afe17df0..4f0b37a2 100644 --- a/src/include/watchdog/wd_internal_commands.h +++ b/src/include/watchdog/wd_internal_commands.h @@ -59,5 +59,5 @@ extern bool get_watchdog_process_needs_cleanup(void); extern void set_watchdog_node_escalated(void); extern void reset_watchdog_node_escalated(void); extern bool get_watchdog_node_escalation_state(void); - +extern size_t wd_ipc_get_shared_mem_size(void); #endif /* WD_INTERNAL_COMMANDS_H */ diff --git a/src/include/watchdog/wd_ipc_conn.h b/src/include/watchdog/wd_ipc_conn.h index aa7ad1d4..f754467c 100644 --- a/src/include/watchdog/wd_ipc_conn.h +++ b/src/include/watchdog/wd_ipc_conn.h @@ -48,6 +48,7 @@ typedef struct WDIPCCmdResult extern void wd_ipc_conn_initialize(void); extern void wd_set_ipc_address(char *socket_dir, int port); +extern size_t estimate_ipc_socket_addr_len(void); extern char *get_watchdog_ipc_address(void); extern WDIPCCmdResult * issue_command_to_watchdog(char type, int timeout_sec, char *data, int data_len, bool blocking); diff --git a/src/main/pgpool_main.c b/src/main/pgpool_main.c index c1529f29..ae7b7ab2 100644 --- a/src/main/pgpool_main.c +++ b/src/main/pgpool_main.c @@ -3276,48 +3276,84 @@ fork_follow_child(int old_main_node, int new_primary, int old_primary) } + static void initialize_shared_mem_objects(bool clear_memcache_oidmaps) { - int size, - i; + BackendDesc* backend_desc; + Size size; + int i; /* - * con_info is a 3 dimension array: i corresponds to pgpool child process, - * j corresponds to connection pool in each process and k corresponds to - * backends in each connection pool. - * - * XXX: Before 2010/4/12 this was a 2 dimension array: i corresponds to - * pgpool child process, j corresponds to connection pool in each process. - * Of course this was wrong. + * Calculate the size of required shared memory and try to allocate + * everyting in sigle memory segment */ - size = pool_coninfo_size(); - con_info = pool_shared_memory_create(size); - memset(con_info, 0, size); + size = 256;/* let us have some extra space */ + size += MAXALIGN(sizeof(BackendDesc)); + size += MAXALIGN(pool_coninfo_size()); + size += MAXALIGN(pool_config->num_init_children * (sizeof(ProcessInfo))); + size += MAXALIGN(sizeof(User1SignalSlot)); + size += MAXALIGN(sizeof(POOL_REQUEST_INFO)); + size += MAXALIGN(sizeof(int)); /* for InRecovery */ + size += MAXALIGN(stat_shared_memory_size()); + size += MAXALIGN(health_check_stats_shared_memory_size()); + /* Snapshot Isolation manage area */ + size += MAXALIGN(sizeof(SI_ManageInfo)); + size += MAXALIGN(pool_config->num_init_children * sizeof(pid_t)); + size += MAXALIGN(pool_config->num_init_children * sizeof(pid_t)); + + if (pool_is_shmem_cache()) + { + size += MAXALIGN(pool_shared_memory_cache_size()); + size += MAXALIGN(pool_shared_memory_fsmm_size()); + size += MAXALIGN(pool_hash_size(pool_config->memqcache_max_num_cache)); + } + if (pool_config->memory_cache_enabled || pool_config->enable_shared_relcache) + size += MAXALIGN(sizeof(POOL_QUERY_CACHE_STATS)); - size = pool_config->num_init_children * (sizeof(ProcessInfo)); + if (pool_config->use_watchdog) + { + size += MAXALIGN(wd_ipc_get_shared_mem_size()); + } - ereport(DEBUG1, - (errmsg("ProcessInfo: num_init_children (%d) * sizeof(ProcessInfo) (%zu) = %d bytes requested for shared memory", - pool_config->num_init_children, - sizeof(ProcessInfo), - size))); + ereport(LOG, + (errmsg("allocating (%zu) bytes of shared memory segment",size))); + initialize_shared_memory_main_segment(size); + + /* Move the backend descriptors to shared memory */ + backend_desc = pool_shared_memory_segment_get_chunk(sizeof(BackendDesc)); + memcpy(backend_desc, pool_config->backend_desc,sizeof(BackendDesc)); + pfree(pool_config->backend_desc); + pool_config->backend_desc = backend_desc; - process_info = pool_shared_memory_create(size); - memset(process_info, 0, size); + /* get the shared memory from main segment*/ + con_info = (ConnectionInfo *)pool_shared_memory_segment_get_chunk(pool_coninfo_size()); + process_info = (ProcessInfo *)pool_shared_memory_segment_get_chunk(pool_config->num_init_children * (sizeof(ProcessInfo))); for (i = 0; i < pool_config->num_init_children; i++) - { process_info[i].connection_info = pool_coninfo(i, 0, 0); - } - user1SignalSlot = pool_shared_memory_create(sizeof(User1SignalSlot)); - /* create fail over/switch over event area */ - Req_info = pool_shared_memory_create(sizeof(POOL_REQUEST_INFO)); + user1SignalSlot = (User1SignalSlot *)pool_shared_memory_segment_get_chunk(sizeof(User1SignalSlot)); - ereport(DEBUG1, - (errmsg("Request info are: sizeof(POOL_REQUEST_INFO) %zu bytes requested for shared memory", - sizeof(POOL_REQUEST_INFO)))); + Req_info = (POOL_REQUEST_INFO *)pool_shared_memory_segment_get_chunk(sizeof(POOL_REQUEST_INFO)); + + InRecovery = (int *)pool_shared_memory_segment_get_chunk(sizeof(int)); + + /* Initialize statistics area */ + stat_set_stat_area(pool_shared_memory_segment_get_chunk(stat_shared_memory_size())); + stat_init_stat_area(); + + /* Initialize health check statistics area */ + health_check_stats_init(pool_shared_memory_segment_get_chunk(health_check_stats_shared_memory_size())); + + /* Initialize Snapshot Isolation manage area */ + si_manage_info = (SI_ManageInfo*)pool_shared_memory_segment_get_chunk(sizeof(SI_ManageInfo)); + + si_manage_info->snapshot_waiting_children = + (pid_t*)pool_shared_memory_segment_get_chunk(pool_config->num_init_children * sizeof(pid_t)); + + si_manage_info->commit_waiting_children = + (pid_t*)pool_shared_memory_segment_get_chunk(pool_config->num_init_children * sizeof(pid_t)); /* * Initialize backend status area. From now on, VALID_BACKEND macro can be @@ -3335,13 +3371,8 @@ initialize_shared_mem_objects(bool clear_memcache_oidmaps) Req_info->switching = false; Req_info->request_queue_head = Req_info->request_queue_tail = -1; Req_info->primary_node_id = -2; - InRecovery = pool_shared_memory_create(sizeof(int)); *InRecovery = RECOVERY_INIT; - ereport(DEBUG1, - (errmsg("Recovery management area: sizeof(int) %zu bytes requested for shared memory", - sizeof(int)))); - /* * Initialize shared memory cache */ @@ -3392,28 +3423,13 @@ initialize_shared_mem_objects(bool clear_memcache_oidmaps) pool_init_memqcache_stats(); } - /* Initialize statistics area */ - stat_set_stat_area(pool_shared_memory_create(stat_shared_memory_size())); - stat_init_stat_area(); - - /* Initialize health check statistics area */ - health_check_stats_init(pool_shared_memory_create(health_check_stats_shared_memory_size())); - /* initialize watchdog IPC unix domain socket address */ if (pool_config->use_watchdog) { wd_ipc_initialize_data(); } - /* Initialize Snapshot Isolation manage area */ - size = MAXALIGN(sizeof(SI_ManageInfo)); - si_manage_info = pool_shared_memory_create(size); - memset((void *)si_manage_info, 0, size); - size = MAXALIGN(pool_config->num_init_children * sizeof(pid_t)); - si_manage_info->snapshot_waiting_children = pool_shared_memory_create(size); - si_manage_info->commit_waiting_children = pool_shared_memory_create(size); } - /* * Read the status file */ diff --git a/src/query_cache/pool_memqcache.c b/src/query_cache/pool_memqcache.c index 9c83eaab..2a230ab2 100644 --- a/src/query_cache/pool_memqcache.c +++ b/src/query_cache/pool_memqcache.c @@ -2076,7 +2076,7 @@ pool_init_memory_cache(size_t size) ereport(DEBUG1, (errmsg("memory cache request size : %zd", size))); - shmem = pool_shared_memory_create(size); + shmem = pool_shared_memory_segment_get_chunk(size); return 0; } @@ -2174,7 +2174,7 @@ pool_init_fsmm(size_t size) int maxblock = pool_get_memqcache_blocks(); int encode_value; - fsmm = pool_shared_memory_create(size); + fsmm = pool_shared_memory_segment_get_chunk(size); encode_value = POOL_MAX_FREE_SPACE / POOL_FSMM_RATIO; memset(fsmm, encode_value, maxblock); return 0; @@ -2204,7 +2204,7 @@ static int *pool_fsmm_clock_hand; void pool_allocate_fsmm_clock_hand(void) { - pool_fsmm_clock_hand = pool_shared_memory_create(sizeof(*pool_fsmm_clock_hand)); + pool_fsmm_clock_hand = pool_shared_memory_segment_get_chunk(sizeof(*pool_fsmm_clock_hand)); *pool_fsmm_clock_hand = 0; } @@ -3770,7 +3770,7 @@ static POOL_QUERY_CACHE_STATS * stats; int pool_init_memqcache_stats(void) { - stats = pool_shared_memory_create(sizeof(POOL_QUERY_CACHE_STATS)); + stats = pool_shared_memory_segment_get_chunk(sizeof(POOL_QUERY_CACHE_STATS)); pool_reset_memqcache_stats(); return 0; } @@ -3927,7 +3927,7 @@ pool_hash_init(int nelements) mask = ~0; mask >>= shift; size = (char *) &hh.elements - (char *) &hh + sizeof(POOL_HEADER_ELEMENT) * nelements2; - hash_header = pool_shared_memory_create(size); + hash_header = pool_shared_memory_segment_get_chunk(size); hash_header->nhash = nelements2; hash_header->mask = mask; @@ -3939,7 +3939,7 @@ pool_hash_init(int nelements) #endif size = sizeof(POOL_HASH_ELEMENT) * nelements2; - hash_elements = pool_shared_memory_create(size); + hash_elements = pool_shared_memory_segment_get_chunk(size); #ifdef POOL_HASH_DEBUG ereport(LOG, @@ -3957,6 +3957,30 @@ pool_hash_init(int nelements) return 0; } +size_t +pool_hash_size(int nelements) +{ + size_t size; + int nelements2; /* number of rounded up hash keys */ + int shift; + POOL_HASH_HEADER hh; + + + /* Round up to power of 2 */ + shift = 32; + nelements2 = 1; + do + { + nelements2 <<= 1; + shift--; + } while (nelements2 < nelements); + + size = (char *) &hh.elements - (char *) &hh + sizeof(POOL_HEADER_ELEMENT) * nelements2; + + size += sizeof(POOL_HASH_ELEMENT) * nelements2; + + return size; +} /* * Reset hash table on shared memory "nelements" is max number of * hash keys. The actual number of hash key is rounded up to power of diff --git a/src/utils/pool_shmem.c b/src/utils/pool_shmem.c index 787db3f1..68710427 100644 --- a/src/utils/pool_shmem.c +++ b/src/utils/pool_shmem.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "utils/pool_ipc.h" @@ -35,9 +36,63 @@ #define PG_SHMAT_FLAGS 0 #endif +static void* shared_mem_chunk = NULL; +static char* shared_mem_free_pos = NULL; +static size_t chunk_size = 0; + static void IpcMemoryDetach(int status, Datum shmaddr); static void IpcMemoryDelete(int status, Datum shmId); +void +initialize_shared_memory_main_segment(size_t size) +{ + /* only main process is allowed to create the chunk */ + if (mypid != getpid()) + { + /* should never happen */ + ereport(LOG, (errmsg("initialize_shared_memory_chunk called from invalid process"))); + return; + } + + if (shared_mem_chunk) + return; + + ereport(LOG, + (errmsg("allocating shared memory segment of size: %zu ",size))); + + shared_mem_chunk = pool_shared_memory_create(size); + shared_mem_free_pos = (char*)shared_mem_chunk; + chunk_size = size; + memset(shared_mem_chunk, 0, size); +} + +void * +pool_shared_memory_segment_get_chunk(size_t size) +{ + void *ptr = NULL; + if (mypid != getpid()) + { + /* should never happen */ + ereport(ERROR, + (errmsg("initialize_shared_memory_chunk called from invalid process"))); + return NULL; + } + /* check if we have enough space left in chunk */ + if ((shared_mem_free_pos - (char*)shared_mem_chunk) + size > chunk_size) + { + ereport(ERROR, + (errmsg("no space left in shared memory segment"))); + return NULL; + + } + /* + * return the current shared_mem_free_pos pointer + * and advance it by size + */ + ptr = (void*)shared_mem_free_pos; + shared_mem_free_pos += MAXALIGN(size); + return ptr; +} /* * Create a shared memory segment of the given size and initialize. Also, diff --git a/src/watchdog/wd_internal_commands.c b/src/watchdog/wd_internal_commands.c index f5dacaaa..afab3c58 100644 --- a/src/watchdog/wd_internal_commands.c +++ b/src/watchdog/wd_internal_commands.c @@ -80,7 +80,7 @@ wd_ipc_initialize_data(void) if (ipc_shared_key == NULL) { - ipc_shared_key = pool_shared_memory_create(sizeof(unsigned int)); + ipc_shared_key = pool_shared_memory_segment_get_chunk(sizeof(unsigned int)); *ipc_shared_key = 0; while (*ipc_shared_key == 0) { @@ -90,17 +90,26 @@ wd_ipc_initialize_data(void) if (watchdog_require_cleanup == NULL) { - watchdog_require_cleanup = pool_shared_memory_create(sizeof(bool)); + watchdog_require_cleanup = pool_shared_memory_segment_get_chunk(sizeof(bool)); *watchdog_require_cleanup = false; } if (watchdog_node_escalated == NULL) { - watchdog_node_escalated = pool_shared_memory_create(sizeof(bool)); + watchdog_node_escalated = pool_shared_memory_segment_get_chunk(sizeof(bool)); *watchdog_node_escalated = false; } } +size_t wd_ipc_get_shared_mem_size(void) +{ + size_t size = 0; + size += MAXALIGN(sizeof(unsigned int)); /* ipc_shared_key */ + size += MAXALIGN(sizeof(bool)); /* watchdog_require_cleanup */ + size += MAXALIGN(sizeof(bool)); /* watchdog_node_escalated */ + size += estimate_ipc_socket_addr_len(); + return size; +} /* * function gets the PG backend status of all attached nodes from diff --git a/src/watchdog/wd_ipc_conn.c b/src/watchdog/wd_ipc_conn.c index 1f88f5b0..d84471d2 100644 --- a/src/watchdog/wd_ipc_conn.c +++ b/src/watchdog/wd_ipc_conn.c @@ -67,7 +67,7 @@ void wd_set_ipc_address(char *socket_dir, int port) port); #ifndef POOL_PRIVATE - watchdog_ipc_address = pool_shared_memory_create(strlen(wd_ipc_sock_addr) + 1); + watchdog_ipc_address = pool_shared_memory_segment_get_chunk(strlen(wd_ipc_sock_addr) + 1); strcpy(watchdog_ipc_address, wd_ipc_sock_addr); #else watchdog_ipc_address = pstrdup(wd_ipc_sock_addr); @@ -84,6 +84,11 @@ wd_ipc_conn_initialize(void) } } +size_t estimate_ipc_socket_addr_len(void) +{ + return strlen(pool_config->wd_ipc_socket_dir) + 25; /* wd_ipc_socket_dir/.s.PGPOOLWD_CMD.port*/ +} + char * get_watchdog_ipc_address(void) { diff --git a/src/watchdog/wd_lifecheck.c b/src/watchdog/wd_lifecheck.c index a08fb1bb..d9ff3878 100644 --- a/src/watchdog/wd_lifecheck.c +++ b/src/watchdog/wd_lifecheck.c @@ -569,6 +569,7 @@ fetch_watchdog_nodes_data(void) static void load_watchdog_nodes_from_json(char *json_data, int len) { + size_t shmem_size; json_value *root; json_value *value; int i, @@ -617,9 +618,12 @@ load_watchdog_nodes_from_json(char *json_data, int len) } /* okay we are done, put this in shared memory */ - gslifeCheckCluster = pool_shared_memory_create(sizeof(LifeCheckCluster)); + shmem_size = MAXALIGN(sizeof(LifeCheckCluster)); + shmem_size += MAXALIGN(sizeof(LifeCheckNode) * nodeCount); + + gslifeCheckCluster = pool_shared_memory_create(shmem_size); gslifeCheckCluster->nodeCount = nodeCount; - gslifeCheckCluster->lifeCheckNodes = pool_shared_memory_create(sizeof(LifeCheckNode) * gslifeCheckCluster->nodeCount); + gslifeCheckCluster->lifeCheckNodes = (LifeCheckNode*)((char*)gslifeCheckCluster + MAXALIGN(sizeof(LifeCheckCluster))); for (i = 0; i < nodeCount; i++) { WDNodeInfo *nodeInfo = parse_watchdog_node_info_from_wd_node_json(value->u.array.values[i]);