summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-18 01:52:42 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-18 01:52:42 +0000
commitc5aff7d2d81275f2023345b9e11ca5cacb34665b (patch)
tree1eae1d92a03b0a2cbd1e83b45704a24d8662cf17 /apps
parentc0ae392704e4e19f7c09fae1e753f777133afe8e (diff)
downloadnuttx-c5aff7d2d81275f2023345b9e11ca5cacb34665b.tar.gz
nuttx-c5aff7d2d81275f2023345b9e11ca5cacb34665b.tar.bz2
nuttx-c5aff7d2d81275f2023345b9e11ca5cacb34665b.zip
Add internal API task_reparent(), used in posix_spawn(). Move libc/spawn/lib_ps.c to sched/task_posixspawn.c; Move libc/spawn/spawn.h to include/nuttx/spawn.h
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5531 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'apps')
-rw-r--r--apps/builtin/exec_builtin.c44
-rw-r--r--apps/nshlib/nsh_builtin.c26
-rw-r--r--apps/nshlib/nsh_fileapps.c21
3 files changed, 62 insertions, 29 deletions
diff --git a/apps/builtin/exec_builtin.c b/apps/builtin/exec_builtin.c
index 803d1ef34..60e8b742d 100644
--- a/apps/builtin/exec_builtin.c
+++ b/apps/builtin/exec_builtin.c
@@ -124,7 +124,7 @@ static void bultin_semtake(FAR sem_t *sem)
do
{
ret = sem_wait(sem);
- ASSERT(ret == 0 || errno == EINTR);
+ ASSERT(ret == 0 || get_errno() == EINTR);
}
while (ret != 0);
}
@@ -152,7 +152,7 @@ static int builtin_taskcreate(int index, FAR const char **argv)
if (b == NULL)
{
- errno = ENOENT;
+ set_errno(ENOENT);
return ERROR;
}
@@ -228,7 +228,7 @@ static int builtin_proxy(int argc, char *argv[])
{
/* Remember the errno value. ret is already set to ERROR */
- g_builtin_parms.errcode = errno;
+ g_builtin_parms.errcode = get_errno();
sdbg("ERROR: open of %s failed: %d\n",
g_builtin_parms.redirfile, g_builtin_parms.errcode);
}
@@ -246,7 +246,7 @@ static int builtin_proxy(int argc, char *argv[])
ret = dup2(fd, 1);
if (ret < 0)
{
- g_builtin_parms.errcode = errno;
+ g_builtin_parms.errcode = get_errno();
sdbg("ERROR: dup2 failed: %d\n", g_builtin_parms.errcode);
}
@@ -266,12 +266,18 @@ static int builtin_proxy(int argc, char *argv[])
ret = builtin_taskcreate(g_builtin_parms.index, g_builtin_parms.argv);
if (ret < 0)
{
- g_builtin_parms.errcode = errno;
+ g_builtin_parms.errcode = get_errno();
sdbg("ERROR: builtin_taskcreate failed: %d\n",
g_builtin_parms.errcode);
}
}
+ /* NOTE: There is a logical error here if CONFIG_SCHED_HAVE_PARENT is
+ * defined: The new task is the child of this proxy task, not the
+ * original caller. As a consequence, operations like waitpid() will
+ * fail on the caller's thread.
+ */
+
/* Post the semaphore to inform the parent task that we have completed
* what we need to do.
*/
@@ -340,11 +346,21 @@ static inline int builtin_startproxy(int index, FAR const char **argv,
ret = sched_getparam(0, &param);
if (ret < 0)
{
- errcode = errno;
+ errcode = get_errno();
sdbg("ERROR: sched_getparam failed: %d\n", errcode);
- goto errout;
+ goto errout_with_sem;
}
+ /* Disable pre-emption so that the proxy does not run until we waitpid
+ * is called. This is probably unnecessary since the builtin_proxy has
+ * the same priority as this thread; it should be schedule behind this
+ * task in the ready-to-run list.
+ */
+
+#ifdef CONFIG_SCHED_WAITPID
+ sched_lock();
+#endif
+
/* Start the intermediary/proxy task at the same priority as the parent task. */
proxy = TASK_CREATE("builtin_proxy", param.sched_priority,
@@ -352,9 +368,9 @@ static inline int builtin_startproxy(int index, FAR const char **argv,
(FAR const char **)NULL);
if (proxy < 0)
{
- errcode = errno;
+ errcode = get_errno();
sdbg("ERROR: Failed to start builtin_proxy: %d\n", errcode);
- goto errout;
+ goto errout_with_lock;
}
/* Wait for the proxy to complete its job. We could use waitpid()
@@ -365,7 +381,8 @@ static inline int builtin_startproxy(int index, FAR const char **argv,
ret = waitpid(proxy, &status, 0);
if (ret < 0)
{
- sdbg("ERROR: waitpid() failed: %d\n", errno);
+ sdbg("ERROR: waitpid() failed: %d\n", get_errno());
+ goto errout_with_lock;
}
#else
bultin_semtake(&g_builtin_execsem);
@@ -377,7 +394,12 @@ static inline int builtin_startproxy(int index, FAR const char **argv,
builtin_semgive(&g_builtin_parmsem);
return g_builtin_parms.result;
-errout:
+errout_with_lock:
+#ifdef CONFIG_SCHED_WAITPID
+ sched_unlock();
+#endif
+
+errout_with_sem:
set_errno(errcode);
builtin_semgive(&g_builtin_parmsem);
return ERROR;
diff --git a/apps/nshlib/nsh_builtin.c b/apps/nshlib/nsh_builtin.c
index 343a0824b..0d5a0231c 100644
--- a/apps/nshlib/nsh_builtin.c
+++ b/apps/nshlib/nsh_builtin.c
@@ -131,12 +131,14 @@ int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
{
/* The application was successfully started with pre-emption disabled.
* In the simplest cases, the application will not have run because the
- * the scheduler is locked. but in the case were I/O redirected, a
- * proxy task ran and, as result, so may have the application.
+ * the scheduler is locked. But in the case where I/O was redirected, a
+ * proxy task ran and broke our lock. As result, the application may
+ * have aso ran if its priority was higher than than the priority of
+ * this thread.
*
- * If the application did not run and if the application was not
- * backgrounded, then we need to wait here for the application to
- * exit. This only works works with the following options:
+ * If the application did not run to completion and if the application
+ * was not backgrounded, then we need to wait here for the application
+ * to exit. This only works works with the following options:
*
* - CONFIG_NSH_DISABLEBG - Do not run commands in background
* - CONFIG_SCHED_WAITPID - Required to run external commands in
@@ -156,11 +158,17 @@ int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
{
int rc = 0;
- /* Wait for the application to exit. We did locked the scheduler
+ /* Wait for the application to exit. We did lock the scheduler
* above, but that does not guarantee that the application did not
- * run in the case where I/O was redirected. The scheduler will
- * be unlocked while waitpid is waiting and if the application has
- * not yet run, it will be able to to do so.
+ * already run to completion in the case where I/O was redirected.
+ * Here the scheduler will be unlocked while waitpid is waiting
+ * and if the application has not yet run, it will now be able to
+ * do so.
+ *
+ * Also, if CONFIG_SCHED_HAVE_PARENT is defined waitpid() might fail
+ * even if task is still active: If the I/O was re-directed by a
+ * proxy task, then the ask is a child of the proxy, and not this
+ * task. waitpid() fails with ECHILD in either case.
*/
ret = waitpid(ret, &rc, 0);
diff --git a/apps/nshlib/nsh_fileapps.c b/apps/nshlib/nsh_fileapps.c
index 92146a68d..9ff230f1a 100644
--- a/apps/nshlib/nsh_fileapps.c
+++ b/apps/nshlib/nsh_fileapps.c
@@ -168,12 +168,14 @@ int nsh_fileapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
{
/* The application was successfully started with pre-emption disabled.
* In the simplest cases, the application will not have run because the
- * the scheduler is locked. but in the case were I/O redirected, a
- * proxy task ran and, as result, so may have the application.
+ * the scheduler is locked. But in the case where I/O was redirected, a
+ * proxy task ran and broke our lock. As result, the application may
+ * have aso ran if its priority was higher than than the priority of
+ * this thread.
*
- * If the application did not run and if the application was not
- * backgrounded, then we need to wait here for the application to
- * exit. This only works works with the following options:
+ * If the application did not run to completion and if the application
+ * was not backgrounded, then we need to wait here for the application
+ * to exit. This only works works with the following options:
*
* - CONFIG_NSH_DISABLEBG - Do not run commands in background
* - CONFIG_SCHED_WAITPID - Required to run external commands in
@@ -193,11 +195,12 @@ int nsh_fileapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
{
int rc = 0;
- /* Wait for the application to exit. We did locked the scheduler
+ /* Wait for the application to exit. We did lock the scheduler
* above, but that does not guarantee that the application did not
- * run in the case where I/O was redirected. The scheduler will
- * be unlocked while waitpid is waiting and if the application has
- * not yet run, it will be able to to do so.
+ * already run to completion in the case where I/O was redirected.
+ * Here the scheduler will be unlocked while waitpid is waiting
+ * and if the application has not yet run, it will now be able to
+ * do so.
*/
ret = waitpid(pid, &rc, 0);