Fix a perverse case where vfork() is called from a pthread. Still not recommended

This commit is contained in:
Gregory Nutt 2014-09-29 12:21:34 -06:00
parent b693fb358a
commit 542e706d7d

View File

@ -79,12 +79,12 @@
****************************************************************************/ ****************************************************************************/
#if CONFIG_TASK_NAME_SIZE > 0 #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) FAR struct task_tcb_s *child)
{ {
/* Copy the name from the parent into the child TCB */ /* 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 #else
# define vfork_namesetup(p,c) # define vfork_namesetup(p,c)
@ -106,21 +106,33 @@ 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) FAR struct task_tcb_s *child)
{ {
/* Is the parent a task? or a pthread? */
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; uintptr_t offset;
int i; int i;
/* Get the address correction */ /* Get the address correction */
offset = child->cmn.xcp.regs[REG_SP] - parent->cmn.xcp.regs[REG_SP]; offset = child->cmn.xcp.regs[REG_SP] - parent->xcp.regs[REG_SP];
/* Change the child argv[] to point into its stack (instead of its
* parent's stack).
*/
child->argv = (FAR char **)((uintptr_t)ptcb->argv + offset);
/* Copy the adjusted address for each argument */ /* Copy the adjusted address for each argument */
for (i = 0; i < CONFIG_MAX_TASK_ARGS && parent->argv[i]; i++) for (i = 0; i < CONFIG_MAX_TASK_ARGS && ptcb->argv[i]; i++)
{ {
uintptr_t newaddr = (uintptr_t)parent->argv[i] + offset; uintptr_t newaddr = (uintptr_t)ptcb->argv[i] + offset;
child->argv[i] = (FAR char *)newaddr; child->argv[i] = (FAR char *)newaddr;
} }
@ -128,6 +140,7 @@ static inline void vfork_stackargsetup(FAR struct task_tcb_s *parent,
child->argv[i] = NULL; child->argv[i] = NULL;
} }
}
/**************************************************************************** /****************************************************************************
* Name: vfork_argsetup * Name: vfork_argsetup
@ -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) FAR struct task_tcb_s *child)
{ {
/* Clone the task name */ /* Clone the task name */