diff options
author | patacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679> | 2012-07-28 18:38:13 +0000 |
---|---|---|
committer | patacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679> | 2012-07-28 18:38:13 +0000 |
commit | 10364c669f75885fccf912b695a221a51a0f69e5 (patch) | |
tree | bdfda0ecbd7119b9c3c607e95c9990b75fadf81b /apps/nshlib | |
parent | 3f57f313a16cc756b46e2f07e1e8ef99a9dc174e (diff) | |
download | px4-firmware-10364c669f75885fccf912b695a221a51a0f69e5.tar.gz px4-firmware-10364c669f75885fccf912b695a221a51a0f69e5.tar.bz2 px4-firmware-10364c669f75885fccf912b695a221a51a0f69e5.zip |
Lock the scheduler when starting NSH builtin applications to eliminate race conditions
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4988 7fd9a85b-ad96-42d3-883c-3090e2eb8679
Diffstat (limited to 'apps/nshlib')
-rw-r--r-- | apps/nshlib/nsh_apps.c | 93 | ||||
-rw-r--r-- | apps/nshlib/nsh_parse.c | 6 |
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, ¶m); + 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, ¶m); - 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) |