You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/10/02 13:13:59 UTC

(nuttx-apps) branch master updated: nsh:support wait command to wait task exit.

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new c916f163f nsh:support wait command to wait task exit.
c916f163f is described below

commit c916f163f28810a13c18d29230eecf0ff02e3c5c
Author: anjiahao <an...@xiaomi.com>
AuthorDate: Wed Dec 27 14:57:30 2023 +0800

    nsh:support wait command to wait task exit.
    
    usage like:
      nsh> sleep 10 &
      [5:100]
      nsh>set pid1=$!
      nsh>sleep 15 &
      [6:100]
      nsh>set pid2=$!
      nsh>wait $pid1 $pid2
    
    'wait' command will block nsh from running until pid1 and pid2 finish.
    This is useful for parallel requirements to perform certain tasks
    
    Signed-off-by: anjiahao <an...@xiaomi.com>
---
 nshlib/CMakeLists.txt |   4 ++
 nshlib/Kconfig        |   5 ++
 nshlib/Makefile       |   4 ++
 nshlib/nsh.h          |   5 ++
 nshlib/nsh_command.c  |   5 ++
 nshlib/nsh_parse.c    |  12 ++--
 nshlib/nsh_wait.c     | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 179 insertions(+), 6 deletions(-)

diff --git a/nshlib/CMakeLists.txt b/nshlib/CMakeLists.txt
index ae3b8dcd8..b7d3fc50d 100644
--- a/nshlib/CMakeLists.txt
+++ b/nshlib/CMakeLists.txt
@@ -98,6 +98,10 @@ if(CONFIG_NSH_LIBRARY)
     list(APPEND CSRCS nsh_test.c)
   endif()
 
+  if(NOT CONFIG_NSH_DISABLE_WAIT)
+    list(APPEND CSRCS nsh_wait.c)
+  endif()
+
   if(CONFIG_USBDEV)
     list(APPEND CSRCS nsh_usbconsole.c)
   endif()
diff --git a/nshlib/Kconfig b/nshlib/Kconfig
index b6899b452..72e117c0a 100644
--- a/nshlib/Kconfig
+++ b/nshlib/Kconfig
@@ -699,6 +699,11 @@ config NSH_DISABLE_IRQ_AFFINITY
 	default DEFAULT_SMALL
 	depends on BOARDCTL_IRQ_AFFINITY
 
+config NSH_DISABLE_WAIT
+	bool "Disable wait"
+	default DEFAULT_SMALL
+	depends on SCHED_WAITPID
+
 endmenu
 
 if MMCSD
diff --git a/nshlib/Makefile b/nshlib/Makefile
index fb7aed89c..808d63af5 100644
--- a/nshlib/Makefile
+++ b/nshlib/Makefile
@@ -82,6 +82,10 @@ ifneq ($(CONFIG_NSH_DISABLESCRIPT),y)
 CSRCS += nsh_test.c
 endif
 
+ifneq ($(CONFIG_NSH_DISABLE_WAIT),y)
+CSRCS += nsh_wait.c
+endif
+
 ifeq ($(CONFIG_USBDEV),y)
 CSRCS += nsh_usbconsole.c
 endif
diff --git a/nshlib/nsh.h b/nshlib/nsh.h
index af6cdb058..f6fb38f9a 100644
--- a/nshlib/nsh.h
+++ b/nshlib/nsh.h
@@ -1231,6 +1231,11 @@ int cmd_alias(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
 int cmd_unalias(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
 #endif
 
+#if !defined(CONFIG_NSH_DISABLE_WAIT) && defined(CONFIG_SCHED_WAITPID) && \
+    !defined(CONFIG_DISABLE_PTHREAD)
+int cmd_wait(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
+#endif
+
 /****************************************************************************
  * Name: nsh_extmatch_count
  *
diff --git a/nshlib/nsh_command.c b/nshlib/nsh_command.c
index 6efbbee69..0e3eb593b 100644
--- a/nshlib/nsh_command.c
+++ b/nshlib/nsh_command.c
@@ -666,6 +666,11 @@ static const struct cmdmap_s g_cmdmap[] =
 
 #ifndef CONFIG_NSH_DISABLE_XD
   CMD_MAP("xd",       cmd_xd,       3, 3, "<hex-address> <byte-count>"),
+#endif
+#if !defined(CONFIG_NSH_DISABLE_WAIT) && defined(CONFIG_SCHED_WAITPID) && \
+    !defined(CONFIG_DISABLE_PTHREAD)
+  CMD_MAP("wait",     cmd_wait,     1, CONFIG_NSH_MAXARGUMENTS,
+          "pid1 [pid2 [pid3] ...]"),
 #endif
   CMD_MAP(NULL,       NULL,         1, 1, NULL)
 };
diff --git a/nshlib/nsh_parse.c b/nshlib/nsh_parse.c
index 2119d4b47..d0973ec55 100644
--- a/nshlib/nsh_parse.c
+++ b/nshlib/nsh_parse.c
@@ -504,6 +504,12 @@ static pthread_addr_t nsh_child(pthread_addr_t arg)
 
   _info("BG %s complete\n", carg->argv[0]);
   nsh_releaseargs(carg);
+
+  /* Detach from the pthread since we are not going to join with it.
+   * Otherwise, we would have a memory leak.
+   */
+
+  pthread_detach(pthread_self());
   return (pthread_addr_t)((uintptr_t)ret);
 }
 #endif
@@ -844,12 +850,6 @@ static int nsh_execute(FAR struct nsh_vtbl_s *vtbl,
           goto errout;
         }
 
-      /* Detach from the pthread since we are not going to join with it.
-       * Otherwise, we would have a memory leak.
-       */
-
-      pthread_detach(thread);
-
       nsh_output(vtbl, "%s [%d:%d]\n", argv[0], thread,
                  param.sched_priority);
     }
diff --git a/nshlib/nsh_wait.c b/nshlib/nsh_wait.c
new file mode 100644
index 000000000..c025799ad
--- /dev/null
+++ b/nshlib/nsh_wait.c
@@ -0,0 +1,150 @@
+/****************************************************************************
+ * apps/nshlib/nsh_wait.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/sched.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <pthread.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+#if !defined(CONFIG_NSH_DISABLE_WAIT) && defined(CONFIG_SCHED_WAITPID) && \
+    !defined(CONFIG_DISABLE_PTHREAD)
+
+static const char g_groupid[] = "Group:";
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_wait
+ *
+ * Description:
+ *   Handle 'cmd_wait' command from terminal.
+ *   wait pid1 [pid2 [pid3] ..] - wait for a pid to exit.
+ *
+ * Input Parameters:
+ *   vtbl - The NSH console.
+ *   argc - Amount of argument strings in command.
+ *   argv - The argument strings.
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int cmd_wait(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
+{
+  FAR char *nextline;
+  FAR char *line;
+  char buf[128];
+  char path[32];
+  int status = 0;
+  int ret = OK;
+  pid_t self;
+  pid_t tid;
+  int fd;
+  int i;
+
+  if (argc == 1)
+    {
+      return OK;
+    }
+
+  self = getpid();
+  for (i = 1; i < argc; i++)
+    {
+      tid = atoi(argv[i]);
+      if (tid == 0)
+        {
+          continue;
+        }
+
+      snprintf(path, sizeof(path), "/proc/%d/status", tid);
+      fd = open(path, O_RDONLY);
+      if (fd < 0)
+        {
+          nsh_error(vtbl, g_fmtcmdfailed, argv[0], "wait", NSH_ERRNO);
+          continue;
+        }
+
+      ret = read(fd, buf, sizeof(buf) - 1);
+      if (ret < 0)
+        {
+          nsh_error(vtbl, g_fmtcmdfailed, argv[0], "wait", NSH_ERRNO);
+          close(fd);
+          continue;
+        }
+
+      close(fd);
+      nextline = buf;
+      do
+        {
+          line = nextline;
+          for (nextline++;
+               *nextline != '\0' && *nextline != '\n';
+               nextline++);
+
+          if (*nextline == '\n')
+            {
+              *nextline++ = '\0';
+            }
+          else
+            {
+              nextline = NULL;
+            }
+
+          if (strncmp(line, g_groupid, sizeof(g_groupid) - 1) == 0)
+            {
+              if (atoi(line + sizeof(g_groupid)) == self)
+                {
+                  ret = pthread_join(tid, (FAR pthread_addr_t *)&status);
+                }
+              else
+                {
+                  ret = waitpid(tid, &status, 0);
+                }
+
+              if (ret < 0)
+                {
+                  nsh_error(vtbl, g_fmtcmdfailed,
+                            argv[0], "wait", NSH_ERRNO);
+                }
+
+              break;
+            }
+        }
+      while (nextline != NULL);
+    }
+
+  return ret < 0 ? ret : status;
+}
+
+#endif /* CONFIG_NSH_DISABLE_WAIT */