Skip to content

Commit c916f16

Browse files
anjiahao1xiaoxiang781216
authored andcommitted
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 <[email protected]>
1 parent 8d1966e commit c916f16

File tree

7 files changed

+179
-6
lines changed

7 files changed

+179
-6
lines changed

nshlib/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ if(CONFIG_NSH_LIBRARY)
9898
list(APPEND CSRCS nsh_test.c)
9999
endif()
100100

101+
if(NOT CONFIG_NSH_DISABLE_WAIT)
102+
list(APPEND CSRCS nsh_wait.c)
103+
endif()
104+
101105
if(CONFIG_USBDEV)
102106
list(APPEND CSRCS nsh_usbconsole.c)
103107
endif()

nshlib/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,11 @@ config NSH_DISABLE_IRQ_AFFINITY
699699
default DEFAULT_SMALL
700700
depends on BOARDCTL_IRQ_AFFINITY
701701

702+
config NSH_DISABLE_WAIT
703+
bool "Disable wait"
704+
default DEFAULT_SMALL
705+
depends on SCHED_WAITPID
706+
702707
endmenu
703708

704709
if MMCSD

nshlib/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ ifneq ($(CONFIG_NSH_DISABLESCRIPT),y)
8282
CSRCS += nsh_test.c
8383
endif
8484

85+
ifneq ($(CONFIG_NSH_DISABLE_WAIT),y)
86+
CSRCS += nsh_wait.c
87+
endif
88+
8589
ifeq ($(CONFIG_USBDEV),y)
8690
CSRCS += nsh_usbconsole.c
8791
endif

nshlib/nsh.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,11 @@ int cmd_alias(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
12311231
int cmd_unalias(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
12321232
#endif
12331233

1234+
#if !defined(CONFIG_NSH_DISABLE_WAIT) && defined(CONFIG_SCHED_WAITPID) && \
1235+
!defined(CONFIG_DISABLE_PTHREAD)
1236+
int cmd_wait(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
1237+
#endif
1238+
12341239
/****************************************************************************
12351240
* Name: nsh_extmatch_count
12361241
*

nshlib/nsh_command.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,11 @@ static const struct cmdmap_s g_cmdmap[] =
666666

667667
#ifndef CONFIG_NSH_DISABLE_XD
668668
CMD_MAP("xd", cmd_xd, 3, 3, "<hex-address> <byte-count>"),
669+
#endif
670+
#if !defined(CONFIG_NSH_DISABLE_WAIT) && defined(CONFIG_SCHED_WAITPID) && \
671+
!defined(CONFIG_DISABLE_PTHREAD)
672+
CMD_MAP("wait", cmd_wait, 1, CONFIG_NSH_MAXARGUMENTS,
673+
"pid1 [pid2 [pid3] ...]"),
669674
#endif
670675
CMD_MAP(NULL, NULL, 1, 1, NULL)
671676
};

nshlib/nsh_parse.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,12 @@ static pthread_addr_t nsh_child(pthread_addr_t arg)
504504

505505
_info("BG %s complete\n", carg->argv[0]);
506506
nsh_releaseargs(carg);
507+
508+
/* Detach from the pthread since we are not going to join with it.
509+
* Otherwise, we would have a memory leak.
510+
*/
511+
512+
pthread_detach(pthread_self());
507513
return (pthread_addr_t)((uintptr_t)ret);
508514
}
509515
#endif
@@ -844,12 +850,6 @@ static int nsh_execute(FAR struct nsh_vtbl_s *vtbl,
844850
goto errout;
845851
}
846852

847-
/* Detach from the pthread since we are not going to join with it.
848-
* Otherwise, we would have a memory leak.
849-
*/
850-
851-
pthread_detach(thread);
852-
853853
nsh_output(vtbl, "%s [%d:%d]\n", argv[0], thread,
854854
param.sched_priority);
855855
}

nshlib/nsh_wait.c

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/****************************************************************************
2+
* apps/nshlib/nsh_wait.c
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one or more
5+
* contributor license agreements. See the NOTICE file distributed with
6+
* this work for additional information regarding copyright ownership. The
7+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance with the
9+
* License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
* License for the specific language governing permissions and limitations
17+
* under the License.
18+
*
19+
****************************************************************************/
20+
21+
/****************************************************************************
22+
* Included Files
23+
****************************************************************************/
24+
25+
#include <nuttx/config.h>
26+
27+
#include <nuttx/sched.h>
28+
#include <sys/wait.h>
29+
#include <stdio.h>
30+
#include <stdlib.h>
31+
#include <fcntl.h>
32+
#include <pthread.h>
33+
34+
#include "nsh.h"
35+
#include "nsh_console.h"
36+
37+
#if !defined(CONFIG_NSH_DISABLE_WAIT) && defined(CONFIG_SCHED_WAITPID) && \
38+
!defined(CONFIG_DISABLE_PTHREAD)
39+
40+
static const char g_groupid[] = "Group:";
41+
42+
/****************************************************************************
43+
* Public Functions
44+
****************************************************************************/
45+
46+
/****************************************************************************
47+
* Name: cmd_wait
48+
*
49+
* Description:
50+
* Handle 'cmd_wait' command from terminal.
51+
* wait pid1 [pid2 [pid3] ..] - wait for a pid to exit.
52+
*
53+
* Input Parameters:
54+
* vtbl - The NSH console.
55+
* argc - Amount of argument strings in command.
56+
* argv - The argument strings.
57+
*
58+
* Returned Value:
59+
* Zero (OK) on success; a negated errno value on failure.
60+
*
61+
****************************************************************************/
62+
63+
int cmd_wait(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
64+
{
65+
FAR char *nextline;
66+
FAR char *line;
67+
char buf[128];
68+
char path[32];
69+
int status = 0;
70+
int ret = OK;
71+
pid_t self;
72+
pid_t tid;
73+
int fd;
74+
int i;
75+
76+
if (argc == 1)
77+
{
78+
return OK;
79+
}
80+
81+
self = getpid();
82+
for (i = 1; i < argc; i++)
83+
{
84+
tid = atoi(argv[i]);
85+
if (tid == 0)
86+
{
87+
continue;
88+
}
89+
90+
snprintf(path, sizeof(path), "/proc/%d/status", tid);
91+
fd = open(path, O_RDONLY);
92+
if (fd < 0)
93+
{
94+
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "wait", NSH_ERRNO);
95+
continue;
96+
}
97+
98+
ret = read(fd, buf, sizeof(buf) - 1);
99+
if (ret < 0)
100+
{
101+
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "wait", NSH_ERRNO);
102+
close(fd);
103+
continue;
104+
}
105+
106+
close(fd);
107+
nextline = buf;
108+
do
109+
{
110+
line = nextline;
111+
for (nextline++;
112+
*nextline != '\0' && *nextline != '\n';
113+
nextline++);
114+
115+
if (*nextline == '\n')
116+
{
117+
*nextline++ = '\0';
118+
}
119+
else
120+
{
121+
nextline = NULL;
122+
}
123+
124+
if (strncmp(line, g_groupid, sizeof(g_groupid) - 1) == 0)
125+
{
126+
if (atoi(line + sizeof(g_groupid)) == self)
127+
{
128+
ret = pthread_join(tid, (FAR pthread_addr_t *)&status);
129+
}
130+
else
131+
{
132+
ret = waitpid(tid, &status, 0);
133+
}
134+
135+
if (ret < 0)
136+
{
137+
nsh_error(vtbl, g_fmtcmdfailed,
138+
argv[0], "wait", NSH_ERRNO);
139+
}
140+
141+
break;
142+
}
143+
}
144+
while (nextline != NULL);
145+
}
146+
147+
return ret < 0 ? ret : status;
148+
}
149+
150+
#endif /* CONFIG_NSH_DISABLE_WAIT */

0 commit comments

Comments
 (0)