mirror of
https://github.com/Cacti/spine.git
synced 2026-10-23 03:27:10 +09:00
fix: replace deprecated POSIX semaphores with pthread wrapper (#517)
## Summary Fixes #516. Replaces deprecated unnamed POSIX semaphores with a portable pthread-based wrapper. Eliminates all 9 remaining build warnings. Depends on #514 (squashed single commit, rebased on latest develop). ## Approach Spine uses semaphores as atomic counters (`sem_post` + `sem_getvalue` + `sem_trywait`, no blocking `sem_wait`). A pthread mutex + counter wrapper provides identical semantics on all platforms with zero `#ifdef`s. Alternatives considered: - `dispatch_semaphore_t` (macOS GCD): no `getvalue` equivalent, requires platform ifdefs - C11 `_Atomic`: no wait/signal capability - autotools detection: still requires fallback code ## Changes (1 commit) - New `spine_sem.h`: inline `spine_sem_init`, `spine_sem_post`, `spine_sem_getvalue`, `spine_sem_wait`, `spine_sem_trywait`, `spine_sem_destroy` - Replace `#include <semaphore.h>` with `#include "spine_sem.h"` in `common.h` - Update all `sem_t`/`sem_*` references in `spine.c`, `poller.c`, `spine.h` - Add `spine_sem.h` to `EXTRA_DIST` ## Warnings eliminated (9) | File | Function | Count | |------|----------|-------| | `spine.c` | `sem_init` | 3 | | `spine.c` | `sem_getvalue` | 4 | | `poller.c` | `sem_getvalue` | 2 | ## Build result Zero errors, zero warnings. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
This commit is contained in:
1 parent
926d5b66af
commit
c72b91b1be
6 files changed
+113
-25
No files matched your search
+1
-1
@@ -31,7 +31,7 @@ bin_PROGRAMS = spine
|
||||
|
||||
man_MANS = spine.1
|
||||
|
||||
EXTRA_DIST = spine.1 uthash.h
|
||||
EXTRA_DIST = spine.1 uthash.h spine_sem.h
|
||||
|
||||
# Docker targets — require Dockerfile and Dockerfile.dev (from PR #401)
|
||||
.PHONY: docker docker-dev verify cppcheck
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
#include <math.h>
|
||||
#include <mysql.h>
|
||||
#include <netdb.h>
|
||||
#include <semaphore.h>
|
||||
#include "spine_sem.h"
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -44,20 +44,20 @@ void child_cleanup(void *arg) {
|
||||
|
||||
void child_cleanup_thread(void *arg) {
|
||||
UNUSED_PARAMETER(arg);
|
||||
sem_post(&available_threads);
|
||||
spine_sem_post(&available_threads);
|
||||
|
||||
int a_threads_value;
|
||||
sem_getvalue(&available_threads, &a_threads_value);
|
||||
spine_sem_getvalue(&available_threads, &a_threads_value);
|
||||
|
||||
SPINE_LOG_DEVDBG(("DEBUG: Available Threads is %i (%i outstanding)", a_threads_value, set.threads - a_threads_value));
|
||||
}
|
||||
|
||||
void child_cleanup_script(void *arg) {
|
||||
UNUSED_PARAMETER(arg);
|
||||
sem_post(&available_scripts);
|
||||
spine_sem_post(&available_scripts);
|
||||
|
||||
int a_scripts_value;
|
||||
sem_getvalue(&available_scripts, &a_scripts_value);
|
||||
spine_sem_getvalue(&available_scripts, &a_scripts_value);
|
||||
|
||||
SPINE_LOG_DEVDBG(("DEBUG: Available Scripts is %i (%i outstanding)", a_scripts_value, MAX_SIMULTANEOUS_SCRIPTS - a_scripts_value));
|
||||
}
|
||||
@@ -99,7 +99,7 @@ void *child(void *arg) {
|
||||
thread_mutex_unlock(LOCK_HOST_TIME);
|
||||
|
||||
/* Allows main thread to proceed with creation of other threads */
|
||||
sem_post(poller_details.thread_init_sem);
|
||||
spine_sem_post(poller_details.thread_init_sem);
|
||||
|
||||
if (is_debug_device(host_id)) {
|
||||
SPINE_LOG(("DEBUG: Device[%i] HT[%i] In Poller, About to Start Polling", host_id, host_thread));
|
||||
@@ -2330,7 +2330,7 @@ char *exec_poll(host_t *current_host, char *command, int id, const char *type) {
|
||||
|
||||
// use the script server timeout value, allow for 50% leeway
|
||||
while (++retries < (set.script_timeout * 15)) {
|
||||
sem_err = sem_trywait(&available_scripts);
|
||||
sem_err = spine_sem_trywait(&available_scripts);
|
||||
if (sem_err == 0) {
|
||||
break;
|
||||
} else if (sem_err == EAGAIN || sem_err == EWOULDBLOCK) {
|
||||
|
||||
@@ -101,8 +101,8 @@
|
||||
/* Global Variables */
|
||||
int entries = 0;
|
||||
int num_hosts = 0;
|
||||
sem_t available_threads;
|
||||
sem_t available_scripts;
|
||||
spine_sem_t available_threads;
|
||||
spine_sem_t available_scripts;
|
||||
double start_time;
|
||||
double total_time;
|
||||
|
||||
@@ -202,7 +202,7 @@ int main(int argc, char *argv[]) {
|
||||
double host_time_double = 0;
|
||||
int items_per_thread = 0;
|
||||
int device_threads;
|
||||
sem_t thread_init_sem;
|
||||
spine_sem_t thread_init_sem;
|
||||
int a_threads_value;
|
||||
//struct timespec until_spec;
|
||||
|
||||
@@ -719,19 +719,19 @@ int main(int argc, char *argv[]) {
|
||||
init_mutexes();
|
||||
|
||||
/* initialize available_threads semaphore */
|
||||
sem_init(&available_threads, 0, set.threads);
|
||||
spine_sem_init(&available_threads, set.threads);
|
||||
|
||||
/* initialize available_scripts semaphore */
|
||||
sem_init(&available_scripts, 0, MAX_SIMULTANEOUS_SCRIPTS);
|
||||
spine_sem_init(&available_scripts, MAX_SIMULTANEOUS_SCRIPTS);
|
||||
|
||||
/* initialize thread initialization semaphore */
|
||||
sem_init(&thread_init_sem, 0, 1);
|
||||
spine_sem_init(&thread_init_sem, 1);
|
||||
|
||||
/* specify the point of timeout for timedwait semaphores */
|
||||
//until_spec.tv_sec = (time_t)(set.poller_interval + begin_time - 0.2);
|
||||
//until_spec.tv_nsec = 0;
|
||||
|
||||
sem_getvalue(&available_threads, &a_threads_value);
|
||||
spine_sem_getvalue(&available_threads, &a_threads_value);
|
||||
SPINE_LOG_HIGH(("DEBUG: Initial Value of Available Threads is %i (%i outstanding)", a_threads_value, set.threads - a_threads_value));
|
||||
|
||||
/* tell fork processes that they are now active */
|
||||
@@ -864,7 +864,7 @@ int main(int argc, char *argv[]) {
|
||||
spine_timeout = FALSE;
|
||||
|
||||
while (TRUE) {
|
||||
sem_err = sem_trywait(&available_threads);
|
||||
sem_err = spine_sem_trywait(&available_threads);
|
||||
|
||||
if (sem_err == 0) {
|
||||
/* acquired a thread */
|
||||
@@ -906,7 +906,7 @@ int main(int argc, char *argv[]) {
|
||||
loop_count = 0;
|
||||
|
||||
while (!spine_timeout) {
|
||||
sem_err = sem_trywait(&thread_init_sem);
|
||||
sem_err = spine_sem_trywait(&thread_init_sem);
|
||||
|
||||
if (sem_err == 0) {
|
||||
// Acquired a thread
|
||||
@@ -960,10 +960,10 @@ int main(int argc, char *argv[]) {
|
||||
device_counter++;
|
||||
}
|
||||
|
||||
sem_getvalue(&available_threads, &a_threads_value);
|
||||
spine_sem_getvalue(&available_threads, &a_threads_value);
|
||||
SPINE_LOG_HIGH(("DEBUG: Device[%i] Available Threads is %i (%i outstanding)", poller_details->host_id, a_threads_value, set.threads - a_threads_value));
|
||||
|
||||
sem_post(&thread_init_sem);
|
||||
spine_sem_post(&thread_init_sem);
|
||||
|
||||
SPINE_LOG_DEVDBG(("DEBUG: DTS: device = %d, host_id = %d, host_thread = %d,"
|
||||
" host_threads = %d, host_data_ids = %d, complete = %d",
|
||||
@@ -984,12 +984,12 @@ int main(int argc, char *argv[]) {
|
||||
/* Restore thread initialization semaphore if thread creation failed */
|
||||
if (thread_status) {
|
||||
thread_mutex_unlock(LOCK_HOST_TIME);
|
||||
sem_post(&thread_init_sem);
|
||||
spine_sem_post(&thread_init_sem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sem_getvalue(&available_threads, &a_threads_value);
|
||||
spine_sem_getvalue(&available_threads, &a_threads_value);
|
||||
|
||||
/* wait for all threads to 'complete'
|
||||
* using the mutex here as the semaphore will
|
||||
@@ -1004,7 +1004,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
SPINE_LOG_HIGH(("NOTE: Polling sleeping while waiting for %d Threads to End", set.threads - a_threads_value));
|
||||
usleep(500000);
|
||||
sem_getvalue(&available_threads, &a_threads_value);
|
||||
spine_sem_getvalue(&available_threads, &a_threads_value);
|
||||
}
|
||||
|
||||
threads_final = set.threads - a_threads_value;
|
||||
|
||||
@@ -499,7 +499,7 @@ typedef struct poller_thread {
|
||||
int complete;
|
||||
char host_time[40];
|
||||
double host_time_double;
|
||||
sem_t *thread_init_sem;
|
||||
spine_sem_t *thread_init_sem;
|
||||
} poller_thread_t;
|
||||
|
||||
/*! PHP Script Server Structure
|
||||
@@ -630,8 +630,8 @@ extern config_t set;
|
||||
extern php_t *php_processes;
|
||||
extern char start_datetime[20];
|
||||
extern char config_paths[CONFIG_PATHS][BUFSIZE];
|
||||
extern sem_t available_threads;
|
||||
extern sem_t available_scripts;
|
||||
extern spine_sem_t available_threads;
|
||||
extern spine_sem_t available_scripts;
|
||||
extern pool_t *db_pool_remote;
|
||||
extern pool_t *db_pool_local;
|
||||
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
+-------------------------------------------------------------------------+
|
||||
| Copyright (C) 2004-2026 The Cacti Group |
|
||||
| |
|
||||
| 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 2 |
|
||||
| of the License, or (at your option) any later version. |
|
||||
+-------------------------------------------------------------------------+
|
||||
| Cacti: The Complete RRDtool-based Graphing Solution |
|
||||
+-------------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef SPINE_SEM_H
|
||||
#define SPINE_SEM_H
|
||||
|
||||
/*
|
||||
* Portable counting semaphore using pthreads.
|
||||
*
|
||||
* macOS deprecated unnamed POSIX semaphores (sem_init, sem_getvalue).
|
||||
* This wrapper provides the same counting semantics using a pthread
|
||||
* mutex + condition variable, which works on all POSIX platforms.
|
||||
*
|
||||
* Spine uses semaphores as atomic counters (sem_post, sem_getvalue, sem_trywait).
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
int value;
|
||||
} spine_sem_t;
|
||||
|
||||
static inline int spine_sem_init(spine_sem_t *s, int value) {
|
||||
if (pthread_mutex_init(&s->mutex, NULL) != 0) return -1;
|
||||
if (pthread_cond_init(&s->cond, NULL) != 0) {
|
||||
pthread_mutex_destroy(&s->mutex);
|
||||
return -1;
|
||||
}
|
||||
s->value = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int spine_sem_post(spine_sem_t *s) {
|
||||
pthread_mutex_lock(&s->mutex);
|
||||
s->value++;
|
||||
pthread_cond_signal(&s->cond);
|
||||
pthread_mutex_unlock(&s->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int spine_sem_getvalue(spine_sem_t *s, int *val) {
|
||||
pthread_mutex_lock(&s->mutex);
|
||||
*val = s->value;
|
||||
pthread_mutex_unlock(&s->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int spine_sem_wait(spine_sem_t *s) {
|
||||
pthread_mutex_lock(&s->mutex);
|
||||
while (s->value <= 0)
|
||||
pthread_cond_wait(&s->cond, &s->mutex);
|
||||
s->value--;
|
||||
pthread_mutex_unlock(&s->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int spine_sem_trywait(spine_sem_t *s) {
|
||||
pthread_mutex_lock(&s->mutex);
|
||||
if (s->value <= 0) {
|
||||
pthread_mutex_unlock(&s->mutex);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
s->value--;
|
||||
pthread_mutex_unlock(&s->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int spine_sem_destroy(spine_sem_t *s) {
|
||||
pthread_mutex_destroy(&s->mutex);
|
||||
pthread_cond_destroy(&s->cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SPINE_SEM_H */
|
||||
Reference in new issue
Block a user