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;
 }
 
 /****************************************************************************

Reply via email to