This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit e3e39331382b307e4efd08ad567d758c43460d01 Author: wenquan1 <[email protected]> AuthorDate: Thu Sep 17 09:25:23 2026 +0800 netutils/ptpd: use status file for ptpd_status IPC Replace the sigqueue + shared-memory IPC mechanism in ptpd_status() with a file-based approach: - Daemon side: on SIGUSR1, write a binary ptpd_status_s struct to a temp file and atomically rename it to the status path. - Client side: send kill(SIGUSR1), poll for the file to appear, then read the struct back. This removes the CONFIG_BUILD_FLAT restriction (the old code returned -ENOTSUP for Protected and Kernel builds) and avoids passing pointers across address spaces via sigqueue. The status file path is configurable via NETUTILS_PTPD_STATUSFILE (default /tmp/ptpd.status). The atomic temp + rename pattern ensures readers never see a partial write. Signed-off-by: wenquan1 <[email protected]> --- netutils/ptpd/Kconfig | 10 +++ netutils/ptpd/ptpd.c | 174 ++++++++++++++++++++++++++------------------------ 2 files changed, 101 insertions(+), 83 deletions(-) diff --git a/netutils/ptpd/Kconfig b/netutils/ptpd/Kconfig index 63d756ad9..b27143ba2 100644 --- a/netutils/ptpd/Kconfig +++ b/netutils/ptpd/Kconfig @@ -189,4 +189,14 @@ config NETUTILS_PTPD_DELAYREQ_AVGCOUNT ---help--- Measured path delay is averaged over this many samples. +config NETUTILS_PTPD_STATUSFILE + string "PTP daemon status file path" + default "/tmp/ptpd.status" + ---help--- + Path where the PTP daemon writes its binary status file + when signaled with SIGUSR1. The ptpd_status() API reads + this file to retrieve daemon state without requiring shared + memory, making it work across all build modes (Flat, + Protected, Kernel). Written atomically via temp + rename. + endif # NETUTILS_PTPD diff --git a/netutils/ptpd/ptpd.c b/netutils/ptpd/ptpd.c index 8bb897a34..e528da8a9 100644 --- a/netutils/ptpd/ptpd.c +++ b/netutils/ptpd/ptpd.c @@ -53,6 +53,7 @@ #include <net/if.h> #include <sys/ioctl.h> #include <sys/poll.h> +#include <sys/stat.h> #include <nuttx/clock.h> #include <nuttx/net/netconfig.h> #include <netutils/ptpd.h> @@ -64,22 +65,14 @@ * Private Types ****************************************************************************/ -/* Carrier structure for querying PTPD status */ - -struct ptpd_statusreq_s -{ - FAR sem_t *done; - FAR struct ptpd_status_s *dest; -}; - /* Main PTPD state storage */ struct ptp_state_s { - /* Request for PTPD task to stop or report status */ + /* Request for PTPD task to stop or dump status */ bool stop; - struct ptpd_statusreq_s status_req; + bool dump; /* Set by SIGUSR1, checked in main loop */ /* Address of network interface we are operating on */ @@ -1551,10 +1544,9 @@ static void ptp_signal_handler(int signo, FAR siginfo_t *siginfo, { state->stop = true; } - else if (signo == SIGUSR1 && siginfo->si_value.sival_ptr) + else if (signo == SIGUSR1) { - state->status_req = - *(FAR struct ptpd_statusreq_s *)siginfo->si_value.sival_ptr; + state->dump = true; } } @@ -1571,75 +1563,87 @@ static void ptp_setup_sighandlers(FAR struct ptp_state_s *state) sigaction(SIGUSR1, &act, NULL); } -/* Process status information request */ +/* Dump status to file when requested via signal. + * Write atomically: temp file + rename. + */ -static void ptp_process_statusreq(FAR struct ptp_state_s *state) +static void ptp_dump_status_file(FAR struct ptp_state_s *state) { - FAR struct ptpd_status_s *status; + struct ptpd_status_s status; + char tmppath[64]; + int fd; + int ret; - if (!state->status_req.dest) + if (!state->dump) { - return; /* No active request */ + return; } - status = state->status_req.dest; - status->clock_source_valid = state->selected_source_valid; + state->dump = false; - if (status->clock_source_valid) - { - /* Copy relevant parts of announce info to status struct */ + memset(&status, 0, sizeof(status)); + status.clock_source_valid = state->selected_source_valid; + if (status.clock_source_valid) + { FAR struct ptp_announce_s *s = &state->selected_source; - memcpy(status->clock_source_info.id, + memcpy(status.clock_source_info.id, s->header.sourceidentity, - sizeof(status->clock_source_info.id)); + sizeof(status.clock_source_info.id)); - status->clock_source_info.utcoffset = + status.clock_source_info.utcoffset = (int16_t)(((uint16_t)s->utcoffset[0] << 8) | s->utcoffset[1]); - status->clock_source_info.priority1 = s->gm_priority1; - status->clock_source_info.clockclass = s->gm_quality[0]; - status->clock_source_info.accuracy = s->gm_quality[1]; - status->clock_source_info.priority2 = s->gm_priority2; - status->clock_source_info.variance = + status.clock_source_info.priority1 = s->gm_priority1; + status.clock_source_info.clockclass = s->gm_quality[0]; + status.clock_source_info.accuracy = s->gm_quality[1]; + status.clock_source_info.priority2 = s->gm_priority2; + status.clock_source_info.variance = ((uint16_t)s->gm_quality[2] << 8) | s->gm_quality[3]; - memcpy(status->clock_source_info.gm_id, + memcpy(status.clock_source_info.gm_id, s->gm_identity, - sizeof(status->clock_source_info.gm_id)); + sizeof(status.clock_source_info.gm_id)); - status->clock_source_info.stepsremoved = + status.clock_source_info.stepsremoved = ((uint16_t)s->stepsremoved[0] << 8) | s->stepsremoved[1]; - status->clock_source_info.timesource = s->timesource; + status.clock_source_info.timesource = s->timesource; } - /* Copy latest adjustment info */ + status.last_clock_update = state->last_delta_timestamp; + status.last_delta_ns = state->last_delta_ns; + status.last_adjtime_ns = state->last_adjtime_ns; + status.drift_ppb = state->drift_ppb; + status.path_delay_ns = state->path_delay_ns; - status->last_clock_update = state->last_delta_timestamp; - status->last_delta_ns = state->last_delta_ns; - status->last_adjtime_ns = state->last_adjtime_ns; - status->drift_ppb = state->drift_ppb; - status->path_delay_ns = state->path_delay_ns; + status.last_received_multicast = state->last_received_multicast; + status.last_received_announce = state->last_received_announce; + status.last_received_sync = state->last_received_sync; + status.last_transmitted_sync = state->last_transmitted_sync; + status.last_transmitted_announce = state->last_transmitted_announce; + status.last_transmitted_delayresp = state->last_transmitted_delayresp; + status.last_transmitted_delayreq = state->last_transmitted_delayreq; - /* Copy timestamps */ + snprintf(tmppath, sizeof(tmppath), "%s.tmp", + CONFIG_NETUTILS_PTPD_STATUSFILE); - status->last_received_multicast = state->last_received_multicast; - status->last_received_announce = state->last_received_announce; - status->last_received_sync = state->last_received_sync; - status->last_transmitted_sync = state->last_transmitted_sync; - status->last_transmitted_announce = state->last_transmitted_announce; - status->last_transmitted_delayresp = state->last_transmitted_delayresp; - status->last_transmitted_delayreq = state->last_transmitted_delayreq; + fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); + if (fd < 0) + { + return; + } - /* Post semaphore to inform that we are done */ + ret = write(fd, &status, sizeof(status)); + close(fd); - if (state->status_req.done) + if (ret == sizeof(status)) { - sem_post(state->status_req.done); + rename(tmppath, CONFIG_NETUTILS_PTPD_STATUSFILE); + } + else + { + unlink(tmppath); } - - state->status_req.done = NULL; - state->status_req.dest = NULL; } /**************************************************************************** @@ -1763,7 +1767,7 @@ int ptpd_start(FAR const struct ptpd_config_s *config) ptp_periodic_send(state); state->selected_source_valid = is_selected_source_valid(state); - ptp_process_statusreq(state); + ptp_dump_status_file(state); } errout: @@ -1796,48 +1800,52 @@ errout: int ptpd_status(int pid, FAR struct ptpd_status_s *status) { -#ifndef CONFIG_BUILD_FLAT + int fd; + int ret; + int elapsed; - /* TODO: Use SHM memory to pass the status information if processes - * do not share the same memory space. - */ + memset(status, 0, sizeof(struct ptpd_status_s)); - return -ENOTSUP; + /* Signal daemon to dump fresh status */ -#else + unlink(CONFIG_NETUTILS_PTPD_STATUSFILE); - int ret = OK; - sem_t donesem; - struct ptpd_statusreq_s req; - union sigval val; - struct timespec timeout; + if (kill(pid, SIGUSR1) != OK) + { + return -errno; + } - /* Fill in the status request */ + /* Wait for status file to appear (up to 3s) */ - memset(status, 0, sizeof(struct ptpd_status_s)); - sem_init(&donesem, 0, 0); - req.done = &donesem; - req.dest = status; - val.sival_ptr = &req; + for (elapsed = 0; elapsed < 30; elapsed++) + { + usleep(100000); + if (access(CONFIG_NETUTILS_PTPD_STATUSFILE, F_OK) == 0) + { + break; + } + } - if (sigqueue(pid, SIGUSR1, val) != OK) + if (elapsed >= 30) + { + return -ETIMEDOUT; + } + + fd = open(CONFIG_NETUTILS_PTPD_STATUSFILE, O_RDONLY | O_CLOEXEC); + if (fd < 0) { return -errno; } - /* Wait for status request to be handled */ + ret = read(fd, status, sizeof(*status)); + close(fd); - clock_gettime(CLOCK_MONOTONIC, &timeout); - timeout.tv_sec += 1; - if (sem_clockwait(&donesem, CLOCK_MONOTONIC, &timeout) != 0) + if (ret != sizeof(*status)) { - ret = -errno; + return ret < 0 ? -errno : -EIO; } - sem_destroy(&donesem); - return ret; - -#endif /* CONFIG_BUILD_FLAT */ + return OK; } /****************************************************************************
