summaryrefslogtreecommitdiff
path: root/apps/nshlib
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-07-28 18:38:13 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-07-28 18:38:13 +0000
commitf29332dabb08e793f12bfaaf49d851052f3d8bb0 (patch)
treebdfda0ecbd7119b9c3c607e95c9990b75fadf81b /apps/nshlib
parent51f1a88cb89e90f522a94c1dfe5ae16f17465121 (diff)
downloadnuttx-f29332dabb08e793f12bfaaf49d851052f3d8bb0.tar.gz
nuttx-f29332dabb08e793f12bfaaf49d851052f3d8bb0.tar.bz2
nuttx-f29332dabb08e793f12bfaaf49d851052f3d8bb0.zip
Lock the scheduler when starting NSH builtin applications to eliminate race conditions
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4988 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'apps/nshlib')
-rw-r--r--apps/nshlib/nsh_apps.c93
-rw-r--r--apps/nshlib/nsh_parse.c6
2 files changed, 67 insertions, 32 deletions
diff --git a/apps/nshlib/nsh_apps.c b/apps/nshlib/nsh_apps.c
index eb019f57b..e335c2e2c 100644
--- a/apps/nshlib/nsh_apps.c
+++ b/apps/nshlib/nsh_apps.c
@@ -90,7 +90,9 @@
* Attempt to execute the application task whose name is 'cmd'
*
* Returned Value:
- * -1 (ERRROR) if the application task corresponding to 'cmd' could not
+ * <0 If exec_namedapp() fails, then the negated errno value
+ * is returned.
+ * -1 (ERROR) if the application task corresponding to 'cmd' could not
* be started (possibly because it doesn not exist).
* 0 (OK) if the application task corresponding to 'cmd' was
* and successfully started. If CONFIG_SCHED_WAITPID is
@@ -107,45 +109,76 @@ int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
{
int ret = OK;
- /* Try to find command within pre-built application list. */
+ /* Lock the scheduler to prevent the application from running until the
+ * waitpid() has been called.
+ */
+
+ sched_lock();
+
+ /* Try to find and execute the command within the list of builtin
+ * applications.
+ */
ret = exec_namedapp(cmd, (FAR const char **)argv);
- if (ret < 0)
+ if (ret >= 0)
{
- return -errno;
- }
+ /* The application was successfully started (but still blocked because the
+ * scheduler is locked). If the application was not backgrounded, then we
+ * need to wait here for the application to exit.
+ */
#ifdef CONFIG_SCHED_WAITPID
- if (vtbl->np.np_bg == false)
- {
- int rc = 0;
-
- waitpid(ret, &rc, 0);
-
- /* We can't return the exact status (nsh has nowhere to put it)
- * so just pass back zero/nonzero in a fashion that doesn't look
- * like an error.
- */
+ if (vtbl->np.np_bg == false)
+ {
+ int rc = 0;
+
+ /* Wait for the application to exit. Since we have locked the
+ * scheduler above, we know that the application has not yet
+ * started and there is no possibility that it has already exited.
+ * The scheduler will be unlocked while waitpid is waiting and the
+ * application will be able to run.
+ */
+
+ ret = waitpid(ret, &rc, 0);
+ if (ret >= 0)
+ {
+ /* We can't return the exact status (nsh has nowhere to put it)
+ * so just pass back zero/nonzero in a fashion that doesn't look
+ * like an error.
+ */
+
+ ret = (rc == 0) ? OK : 1;
+
+ /* TODO: Set the environment variable '?' to a string corresponding
+ * to WEXITSTATUS(rc) so that $? will expand to the exit status of
+ * the most recently executed task.
+ */
+ }
+ }
+ else
+#endif
+ {
+ struct sched_param param;
+ sched_getparam(0, &param);
+ nsh_output(vtbl, "%s [%d:%d]\n", cmd, ret, param.sched_priority);
- ret = (rc == 0) ? OK : 1;
+ /* Backgrounded commands always 'succeed' as long as we can start
+ * them.
+ */
- /* TODO: Set the environment variable '?' to a string corresponding
- * to WEXITSTATUS(rc) so that $? will expand to the exit status of
- * the most recently executed task.
- */
+ ret = OK;
+ }
}
- else
-#endif
- {
- struct sched_param param;
- sched_getparam(0, &param);
- nsh_output(vtbl, "%s [%d:%d]\n", cmd, ret, param.sched_priority);
- /* Backgrounded commands always 'succeed' as long as we can start
- * them.
- */
+ sched_unlock();
- ret = OK;
+ /* If exec_namedapp() or waitpid() failed, then return the negated errno
+ * value.
+ */
+
+ if (ret < 0)
+ {
+ return -errno;
}
return ret;
diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c
index 64850eb62..93171abf7 100644
--- a/apps/nshlib/nsh_parse.c
+++ b/apps/nshlib/nsh_parse.c
@@ -492,6 +492,8 @@ static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
* Exectue the command in argv[0]
*
* Returned Value:
+ * <0 If exec_namedapp() fails, then the negated errno value
+ * is returned.
* -1 (ERRROR) if the command was unsuccessful
* 0 (OK) if the command was successful
* 1 if an application task was spawned successfully, but
@@ -521,8 +523,8 @@ static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, int argc, char *argv[])
#ifdef CONFIG_NSH_BUILTIN_APPS
ret = nsh_execapp(vtbl, cmd, argv);
- /* The pre-built application was successfully started -- return OK
- * or 1 if it returned a non-zero exit status.
+ /* If the built-in application was successfully started, return OK
+ * or 1 (if the application returned a non-zero exit status).
*/
if (ret >= 0)