--- lbbs/src/menu.c 2025/10/18 12:06:10 1.75 +++ lbbs/src/menu.c 2025/11/04 13:49:51 1.80 @@ -1,18 +1,10 @@ -/*************************************************************************** - menu.c - description - ------------------- - Copyright : (C) 2004-2025 by Leaflet - Email : leaflet@leafok.com - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * menu + * - configurable user interactive menu feature + * + * Copyright (C) 2004-2025 by Leaflet + */ #include "bbs.h" #include "bbs_cmd.h" @@ -38,6 +30,8 @@ #define MENU_SET_RESERVED_LENGTH (sizeof(int16_t) * 4) +#define MENU_SHMGET_RETRY_LIMIT 10 + MENU_SET bbs_menu; MENU_SET top10_menu; @@ -60,6 +54,7 @@ int load_menu(MENU_SET *p_menu_set, cons int proj_id; key_t key; size_t size; + int retry_cnt; // Initialize the data structure memset(p_menu_set, 0, sizeof(*p_menu_set)); @@ -87,31 +82,47 @@ int load_menu(MENU_SET *p_menu_set, cons } // Allocate shared memory - proj_id = (int)(time(NULL) % getpid()); - key = ftok(conf_file, proj_id); - if (key == -1) - { - log_error("ftok(%s %d) error (%d)\n", conf_file, proj_id, errno); - return -2; - } - size = MENU_SET_RESERVED_LENGTH + sizeof(MENU) * MAX_MENUS + sizeof(MENU_ITEM) * MAX_MENUITEMS + sizeof(MENU_SCREEN) * MAX_MENUS + MAX_MENU_SCR_BUF_LENGTH * MAX_MENUS; - p_menu_set->shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600); - if (p_menu_set->shmid == -1) + + proj_id = (int)(time(NULL) % getpid()); + retry_cnt = 0; + + do { - log_error("shmget(conf_file=%s, proj_id=%d, size = %d) error (%d)\n", conf_file, proj_id, size, errno); - return -3; - } + key = ftok(conf_file, proj_id + retry_cnt); + if (key == -1) + { + log_error("ftok(%s %d) error (%d)\n", conf_file, proj_id, errno); + return -2; + } + + p_menu_set->shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600); + + if (p_menu_set->shmid == -1) + { + if (errno != EEXIST || retry_cnt + 1 >= MENU_SHMGET_RETRY_LIMIT) + { + log_error("shmget(conf_file=%s, size=%d) error (%d) %d times\n", + conf_file, size, errno, retry_cnt + 1); + break; + } + log_error("shmget(conf_file=%s, proj_id=%d, key=0x%x, size=%d) error (%d), retry ...\n", + conf_file, proj_id + retry_cnt, key, size, errno); + retry_cnt++; + } + } while (p_menu_set->shmid == -1); + p_menu_set->p_reserved = shmat(p_menu_set->shmid, NULL, 0); if (p_menu_set->p_reserved == (void *)-1) { log_error("shmat() error (%d)\n", errno); return -3; } + p_menu_set->p_menu_pool = (char *)(p_menu_set->p_reserved) + MENU_SET_RESERVED_LENGTH; p_menu_set->p_menu_item_pool = (char *)(p_menu_set->p_menu_pool) + sizeof(MENU) * MAX_MENUS; p_menu_set->p_menu_screen_pool = (char *)(p_menu_set->p_menu_item_pool) + sizeof(MENU_ITEM) * MAX_MENUITEMS;