From 032086870d16992dcdf820bf93a36c2a6426d6e7 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 13 Jun 2021 13:43:38 +0800 Subject: [PATCH] sched/posix_spawn: Don't insert name at the begin of argv since the standard require the caller pass the name explicitly https://pubs.opengroup.org/onlinepubs/009695399/functions/posix_spawn.html: The argument argv is an array of character pointers to null-terminated strings. The last member of this array shall be a null pointer and is not counted in argc. These strings constitute the argument list available to the new process image. The value in argv[0] should point to a filename that is associated with the process image being started by the posix_spawn() or posix_spawnp() function. Signed-off-by: Xiang Xiao Change-Id: Id79ffcc501ae9552dc4e908418ff555f498be7f1 --- binfmt/binfmt_execmodule.c | 2 +- include/nuttx/sched.h | 22 +++++----- sched/task/task.h | 4 +- sched/task/task_create.c | 3 +- sched/task/task_init.c | 24 ++++++----- sched/task/task_setup.c | 88 ++++++++++++++++++++------------------ sched/task/task_vfork.c | 2 +- 7 files changed, 78 insertions(+), 67 deletions(-) diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c index 620655975c..834176f5cc 100644 --- a/binfmt/binfmt_execmodule.c +++ b/binfmt/binfmt_execmodule.c @@ -168,7 +168,7 @@ int exec_module(FAR const struct binary_s *binp, /* Initialize the task */ - ret = nxtask_init(tcb, filename, binp->priority, + ret = nxtask_init(tcb, false, filename, binp->priority, NULL, binp->stacksize, binp->entrypt, argv); binfmt_freeargv(argv); if (ret < 0) diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 8f324402a7..0be56bc977 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -908,15 +908,16 @@ FAR struct streamlist *nxsched_get_streams(void); * - Task type may be set in the TCB flags to create kernel thread * * Input Parameters: - * tcb - Address of the new task's TCB - * name - Name of the new task (not used) - * priority - Priority of the new task - * stack - Start of the pre-allocated stack - * stack_size - Size (in bytes) of the stack allocated - * entry - Application start point of the new task - * argv - A pointer to an array of input parameters. The array - * should be terminated with a NULL argv[] value. If no - * parameters are required, argv may be NULL. + * tcb - Address of the new task's TCB + * insert_name - Insert name to the first argv + * name - Name of the new task + * priority - Priority of the new task + * stack - Start of the pre-allocated stack + * stack_size - Size (in bytes) of the stack allocated + * entry - Application start point of the new task + * argv - A pointer to an array of input parameters. The array + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. * * Returned Value: * OK on success; negative error value on failure appropriately. (See @@ -927,7 +928,8 @@ FAR struct streamlist *nxsched_get_streams(void); * ****************************************************************************/ -int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, +int nxtask_init(FAR struct task_tcb_s *tcb, bool insert_name, + const char *name, int priority, FAR void *stack, uint32_t stack_size, main_t entry, FAR char * const argv[]); diff --git a/sched/task/task.h b/sched/task/task.h index daea1bd2fa..ab06689842 100644 --- a/sched/task/task.h +++ b/sched/task/task.h @@ -44,8 +44,8 @@ struct tcb_s; /* Forward reference */ void nxtask_start(void); int nxtask_setup_scheduler(FAR struct task_tcb_s *tcb, int priority, start_t start, main_t main, uint8_t ttype); -int nxtask_setup_arguments(FAR struct task_tcb_s *tcb, FAR const char *name, - FAR char * const argv[]); +int nxtask_setup_arguments(FAR struct task_tcb_s *tcb, bool insert_name, + FAR const char *name, FAR char * const argv[]); /* Task exit */ diff --git a/sched/task/task_create.c b/sched/task/task_create.c index 9915c5d8b6..078d8d2d9b 100644 --- a/sched/task/task_create.c +++ b/sched/task/task_create.c @@ -91,7 +91,8 @@ static int nxthread_create(FAR const char *name, uint8_t ttype, /* Initialize the task */ - ret = nxtask_init(tcb, name, priority, NULL, stack_size, entry, argv); + ret = nxtask_init(tcb, true, name, priority, + NULL, stack_size, entry, argv); if (ret < OK) { kmm_free(tcb); diff --git a/sched/task/task_init.c b/sched/task/task_init.c index dfd7c7f1dc..35facff30e 100644 --- a/sched/task/task_init.c +++ b/sched/task/task_init.c @@ -62,15 +62,16 @@ * - Task type may be set in the TCB flags to create kernel thread * * Input Parameters: - * tcb - Address of the new task's TCB - * name - Name of the new task (not used) - * priority - Priority of the new task - * stack - Start of the pre-allocated stack - * stack_size - Size (in bytes) of the stack allocated - * entry - Application start point of the new task - * argv - A pointer to an array of input parameters. The array - * should be terminated with a NULL argv[] value. If no - * parameters are required, argv may be NULL. + * tcb - Address of the new task's TCB + * insert_name - Insert name to the first argv + * name - Name of the new task + * priority - Priority of the new task + * stack - Start of the pre-allocated stack + * stack_size - Size (in bytes) of the stack allocated + * entry - Application start point of the new task + * argv - A pointer to an array of input parameters. The array + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. * * Returned Value: * OK on success; negative error value on failure appropriately. (See @@ -81,7 +82,8 @@ * ****************************************************************************/ -int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, +int nxtask_init(FAR struct task_tcb_s *tcb, bool insert_name, + const char *name, int priority, FAR void *stack, uint32_t stack_size, main_t entry, FAR char * const argv[]) { @@ -153,7 +155,7 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, /* Setup to pass parameters to the new task */ - nxtask_setup_arguments(tcb, name, argv); + nxtask_setup_arguments(tcb, insert_name, name, argv); /* Now we have enough in place that we can join the group */ diff --git a/sched/task/task_setup.c b/sched/task/task_setup.c index 73f681512a..5bac051f05 100644 --- a/sched/task/task_setup.c +++ b/sched/task/task_setup.c @@ -452,13 +452,6 @@ static int nxthread_setup_scheduler(FAR struct tcb_s *tcb, int priority, static void nxtask_setup_name(FAR struct task_tcb_s *tcb, FAR const char *name) { - /* Give a name to the unnamed tasks */ - - if (!name) - { - name = (FAR char *)g_noname; - } - /* Copy the name into the TCB */ strncpy(tcb->cmn.name, name, CONFIG_TASK_NAME_SIZE); @@ -479,21 +472,23 @@ static void nxtask_setup_name(FAR struct task_tcb_s *tcb, * accessible no matter what privilege mode the task runs in. * * Input Parameters: - * tcb - Address of the new task's TCB - * argv - A pointer to an array of input parameters. The arrau should be - * terminated with a NULL argv[] value. If no parameters are - * required, argv may be NULL. + * tcb - Address of the new task's TCB + * insert_name - Insert name to the first entry + * name - Name of the new task + * argv - A pointer to an array of input parameters. The array + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. * * Returned Value: * Zero (OK) on success; a negated errno on failure. * ****************************************************************************/ -static inline int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, - FAR char * const argv[]) +static inline int +nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, bool insert_name, + FAR const char *name, FAR char * const argv[]) { FAR char **stackargv; - FAR const char *name; FAR char *str; size_t strtablen; size_t argvlen; @@ -501,17 +496,9 @@ static inline int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, int argc; int i; - /* Get the name string that we will use as the first argument */ - -#if CONFIG_TASK_NAME_SIZE > 0 - name = tcb->cmn.name; -#else - name = (FAR const char *)g_noname; -#endif /* CONFIG_TASK_NAME_SIZE */ - /* Get the size of the task name (including the NUL terminator) */ - strtablen = (strlen(name) + 1); + strtablen = insert_name ? (strlen(name) + 1) : 0; /* Count the number of arguments and get the accumulated size of the * argument strings (including the null terminators). The argument count @@ -554,7 +541,7 @@ static inline int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, * task name plus a NULL argv[] entry to terminate the list. */ - argvlen = (argc + 2) * sizeof(FAR char *); + argvlen = (insert_name + argc + 1) * sizeof(FAR char *); stackargv = (FAR char **)up_stack_frame(&tcb->cmn, argvlen + strtablen); DEBUGASSERT(stackargv != NULL); @@ -563,6 +550,8 @@ static inline int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, return -ENOMEM; } + tcb->argv = stackargv; + /* Get the address of the string table that will lie immediately after * the argv[] array and mark it as a null string. */ @@ -573,10 +562,13 @@ static inline int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, * NUL terminator in the string buffer. */ - stackargv[0] = str; - nbytes = strlen(name) + 1; - strcpy(str, name); - str += nbytes; + if (insert_name) + { + *stackargv++ = str; + nbytes = strlen(name) + 1; + strcpy(str, name); + str += nbytes; + } /* Copy each argument */ @@ -587,10 +579,10 @@ static inline int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, * argument and its NUL terminator in the string buffer. */ - stackargv[i + 1] = str; - nbytes = strlen(argv[i]) + 1; + *stackargv++ = str; + nbytes = strlen(argv[i]) + 1; strcpy(str, argv[i]); - str += nbytes; + str += nbytes; } /* Put a terminator entry at the end of the argv[] array. Then save the @@ -598,8 +590,7 @@ static inline int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb, * nxtask_start(). */ - stackargv[argc + 1] = NULL; - tcb->argv = stackargv; + *stackargv++ = NULL; return OK; } @@ -696,20 +687,35 @@ int pthread_setup_scheduler(FAR struct pthread_tcb_s *tcb, int priority, * task runs in. * * Input Parameters: - * tcb - Address of the new task's TCB - * name - Name of the new task (not used) - * argv - A pointer to an array of input parameters. The array should be - * terminated with a NULL argv[] value. If no parameters are - * required, argv may be NULL. + * tcb - Address of the new task's TCB + * insert_name - Insert name to the first argv + * name - Name of the new task + * argv - A pointer to an array of input parameters. The array + * should be terminated with a NULL argv[] value. If no + * parameters are required, argv may be NULL. * * Returned Value: * OK * ****************************************************************************/ -int nxtask_setup_arguments(FAR struct task_tcb_s *tcb, FAR const char *name, - FAR char * const argv[]) +int nxtask_setup_arguments(FAR struct task_tcb_s *tcb, bool insert_name, + FAR const char *name, FAR char * const argv[]) { + /* Give a name to the unnamed tasks */ + + if (!name) + { + name = (FAR char *)g_noname; + } + + /* Always insert name if argv equals NULL */ + + if (!argv) + { + insert_name = true; + } + /* Setup the task name */ nxtask_setup_name(tcb, name); @@ -719,5 +725,5 @@ int nxtask_setup_arguments(FAR struct task_tcb_s *tcb, FAR const char *name, * privilege mode the task runs in. */ - return nxtask_setup_stackargs(tcb, argv); + return nxtask_setup_stackargs(tcb, insert_name, name, argv); } diff --git a/sched/task/task_vfork.c b/sched/task/task_vfork.c index b31b73254f..9ff5471e48 100644 --- a/sched/task/task_vfork.c +++ b/sched/task/task_vfork.c @@ -208,7 +208,7 @@ FAR struct task_tcb_s *nxtask_setup_vfork(start_t retaddr) name = parent->cmn.name; #endif - nxtask_setup_arguments(child, name, parent->argv); + nxtask_setup_arguments(child, false, name, parent->argv); /* Now we have enough in place that we can join the group */