diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index ae0700133f..a0eaaec2a1 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -507,6 +507,7 @@ struct task_group_s /* Environment variables **************************************************/ FAR char **tg_envp; /* Allocated environment strings */ + ssize_t tg_envpc; /* Maximum entries of environment array */ ssize_t tg_envc; /* Number of environment strings */ #endif diff --git a/sched/environ/env_dup.c b/sched/environ/env_dup.c index 8ab1ea38e6..8a41b393e9 100644 --- a/sched/environ/env_dup.c +++ b/sched/environ/env_dup.c @@ -88,6 +88,7 @@ int env_dup(FAR struct task_group_s *group, FAR char * const *envcp) } group->tg_envc = envc; + group->tg_envpc = (envc + SCHED_ENVIRON_RESERVED + 1); /* A special case is that the parent has an "empty" environment * allocation, i.e., there is an allocation in place but it @@ -98,7 +99,7 @@ int env_dup(FAR struct task_group_s *group, FAR char * const *envcp) { /* There is an environment, duplicate it */ - envp = group_malloc(group, sizeof(*envp) * (envc + 1)); + envp = group_malloc(group, sizeof(*envp) * group->tg_envpc); if (envp == NULL) { /* The parent's environment can not be inherited due to a diff --git a/sched/environ/env_release.c b/sched/environ/env_release.c index 9d4e510570..9b041aa7a3 100644 --- a/sched/environ/env_release.c +++ b/sched/environ/env_release.c @@ -83,8 +83,9 @@ void env_release(FAR struct task_group_s *group) * task group structure are reset to initial values. */ - group->tg_envp = NULL; - group->tg_envc = 0; + group->tg_envp = NULL; + group->tg_envpc = 0; + group->tg_envc = 0; } #endif /* CONFIG_DISABLE_ENVIRON */ diff --git a/sched/environ/env_removevar.c b/sched/environ/env_removevar.c index 93a10b0270..7ff4707ee9 100644 --- a/sched/environ/env_removevar.c +++ b/sched/environ/env_removevar.c @@ -86,14 +86,17 @@ void env_removevar(FAR struct task_group_s *group, ssize_t index) { group_free(group, group->tg_envp); group->tg_envp = NULL; + group->tg_envpc = 0; } - else + else if (group->tg_envc <= + (group->tg_envpc - SCHED_ENVIRON_RESERVED * 2)) { /* Reallocate the environment to reclaim a little memory */ + group->tg_envpc = group->tg_envc + SCHED_ENVIRON_RESERVED + 1; + group->tg_envp = group_realloc(group, group->tg_envp, - sizeof(*group->tg_envp) * - (group->tg_envc + 1)); + sizeof(*group->tg_envp) * group->tg_envpc); DEBUGASSERT(group->tg_envp != NULL); } } diff --git a/sched/environ/env_setenv.c b/sched/environ/env_setenv.c index bc5850dd0c..6180bc4fc3 100644 --- a/sched/environ/env_setenv.c +++ b/sched/environ/env_setenv.c @@ -71,7 +71,8 @@ int setenv(FAR const char *name, FAR const char *value, int overwrite) FAR struct task_group_s *group; FAR char *pvar; FAR char **envp; - ssize_t envc = 0; + ssize_t envc; + ssize_t envpc; ssize_t ret = OK; int varlen; @@ -153,33 +154,41 @@ int setenv(FAR const char *name, FAR const char *value, int overwrite) goto errout_with_lock; } - if (group->tg_envp) - { - envc = group->tg_envc; - envp = group_realloc(group, group->tg_envp, - sizeof(*envp) * (envc + 2)); - if (envp == NULL) - { - ret = ENOMEM; - goto errout_with_var; - } - } - else - { - envp = group_malloc(group, sizeof(*envp) * 2); - if (envp == NULL) - { - ret = ENOMEM; - goto errout_with_var; - } - } + envc = group->tg_envc; - envp[envc++] = pvar; - envp[envc] = NULL; + if (group->tg_envp == NULL) + { + envpc = SCHED_ENVIRON_RESERVED + 2; + + envp = group_malloc(group, sizeof(*envp) * envpc); + if (envp == NULL) + { + ret = ENOMEM; + goto errout_with_var; + } + + group->tg_envp = envp; + group->tg_envpc = envpc; + } + else if (envc >= group->tg_envpc - 1) + { + envpc = envc + SCHED_ENVIRON_RESERVED + 2; + + envp = group_realloc(group, group->tg_envp, sizeof(*envp) * envpc); + if (envp == NULL) + { + ret = ENOMEM; + goto errout_with_var; + } + + group->tg_envp = envp; + group->tg_envpc = envpc; + } /* Save the new buffer and count */ - group->tg_envp = envp; + group->tg_envp[envc++] = pvar; + group->tg_envp[envc] = NULL; group->tg_envc = envc; /* Now, put the new name=value string into the environment buffer */ diff --git a/sched/environ/environ.h b/sched/environ/environ.h index 615306c736..e1846116db 100644 --- a/sched/environ/environ.h +++ b/sched/environ/environ.h @@ -37,6 +37,8 @@ # define env_release(group) (0) #else +# define SCHED_ENVIRON_RESERVED (4) + /**************************************************************************** * Public Data ****************************************************************************/