diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-09-29 12:21:34 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-09-29 12:21:34 -0600 |
commit | 506e660018db40873b8f97bec663e29bbd2b030e (patch) | |
tree | 6bfee4461845b9e969f11afc8203ee24c1eec8e7 | |
parent | 2e613d3c5fe48fb2eba322d5c2e257d6fe42a417 (diff) | |
download | nuttx-506e660018db40873b8f97bec663e29bbd2b030e.tar.gz nuttx-506e660018db40873b8f97bec663e29bbd2b030e.tar.bz2 nuttx-506e660018db40873b8f97bec663e29bbd2b030e.zip |
Fix a perverse case where vfork() is called from a pthread. Still not recommended
-rw-r--r-- | nuttx/sched/task/task_vfork.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/nuttx/sched/task/task_vfork.c b/nuttx/sched/task/task_vfork.c index 864a29601..ea7ce295b 100644 --- a/nuttx/sched/task/task_vfork.c +++ b/nuttx/sched/task/task_vfork.c @@ -79,12 +79,12 @@ ****************************************************************************/ #if CONFIG_TASK_NAME_SIZE > 0 -static inline void vfork_namesetup(FAR struct task_tcb_s *parent, +static inline void vfork_namesetup(FAR struct tcb_s *parent, FAR struct task_tcb_s *child) { /* Copy the name from the parent into the child TCB */ - strncpy(child->cmn.name, parent->cmn.name, CONFIG_TASK_NAME_SIZE); + strncpy(child->cmn.name, parent->name, CONFIG_TASK_NAME_SIZE); } #else # define vfork_namesetup(p,c) @@ -106,27 +106,40 @@ static inline void vfork_namesetup(FAR struct task_tcb_s *parent, * ****************************************************************************/ -static inline void vfork_stackargsetup(FAR struct task_tcb_s *parent, +static inline void vfork_stackargsetup(FAR struct tcb_s *parent, FAR struct task_tcb_s *child) { - uintptr_t offset; - int i; + /* Is the parent a task? or a pthread? */ - /* Get the address correction */ + child->argv = NULL; + if ((parent->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD) + { + FAR struct task_tcb_s *ptcb = (FAR struct task_tcb_s *)parent; + uintptr_t offset; + int i; - offset = child->cmn.xcp.regs[REG_SP] - parent->cmn.xcp.regs[REG_SP]; + /* Get the address correction */ - /* Copy the adjusted address for each argument */ + offset = child->cmn.xcp.regs[REG_SP] - parent->xcp.regs[REG_SP]; - for (i = 0; i < CONFIG_MAX_TASK_ARGS && parent->argv[i]; i++) - { - uintptr_t newaddr = (uintptr_t)parent->argv[i] + offset; - child->argv[i] = (FAR char *)newaddr; - } + /* Change the child argv[] to point into its stack (instead of its + * parent's stack). + */ + + child->argv = (FAR char **)((uintptr_t)ptcb->argv + offset); - /* Put a terminator entry at the end of the child argv[] array. */ + /* Copy the adjusted address for each argument */ - child->argv[i] = NULL; + for (i = 0; i < CONFIG_MAX_TASK_ARGS && ptcb->argv[i]; i++) + { + uintptr_t newaddr = (uintptr_t)ptcb->argv[i] + offset; + child->argv[i] = (FAR char *)newaddr; + } + + /* Put a terminator entry at the end of the child argv[] array. */ + + child->argv[i] = NULL; + } } /**************************************************************************** @@ -144,7 +157,7 @@ static inline void vfork_stackargsetup(FAR struct task_tcb_s *parent, * ****************************************************************************/ -static inline void vfork_argsetup(FAR struct task_tcb_s *parent, +static inline void vfork_argsetup(FAR struct tcb_s *parent, FAR struct task_tcb_s *child) { /* Clone the task name */ |