Fix a massive memory leak in the run_list_test() function.

Rename run_list_test() as free_pipe_list().
Rename run_pipe_test() as free_pipe().
 -Erik
This commit is contained in:
Eric Andersen 2001-05-23 22:18:35 +00:00
parent 77d9268892
commit bf7df04ec1
2 changed files with 22 additions and 66 deletions

44
hush.c
View File

@ -357,8 +357,8 @@ static void mark_closed(int fd);
static void close_all(); static void close_all();
/* "run" the final data structures: */ /* "run" the final data structures: */
static char *indenter(int i); static char *indenter(int i);
static int run_list_test(struct pipe *head, int indent); static int free_pipe_list(struct pipe *head, int indent);
static int run_pipe_test(struct pipe *pi, int indent); static int free_pipe(struct pipe *pi, int indent);
/* really run the final data structures: */ /* really run the final data structures: */
static int setup_redirects(struct child_prog *prog, int squirrel[]); static int setup_redirects(struct child_prog *prog, int squirrel[]);
static int pipe_wait(struct pipe *pi); static int pipe_wait(struct pipe *pi);
@ -395,7 +395,6 @@ static int parse_file_outer(FILE *f);
static void checkjobs(); static void checkjobs();
static void insert_bg_job(struct pipe *pi); static void insert_bg_job(struct pipe *pi);
static void remove_bg_job(struct pipe *pi); static void remove_bg_job(struct pipe *pi);
static void free_pipe(struct pipe *pi);
/* local variable support */ /* local variable support */
static char *get_local_var(const char *var); static char *get_local_var(const char *var);
static void unset_local_var(const char *name); static void unset_local_var(const char *name);
@ -1138,7 +1137,7 @@ static void pseudo_exec(struct child_prog *child)
debug_printf("runtime nesting to group\n"); debug_printf("runtime nesting to group\n");
interactive=0; /* crucial!!!! */ interactive=0; /* crucial!!!! */
rcode = run_list_real(child->group); rcode = run_list_real(child->group);
/* OK to leak memory by not calling run_list_test, /* OK to leak memory by not calling free_pipe_list,
* since this process is about to exit */ * since this process is about to exit */
_exit(rcode); _exit(rcode);
} else { } else {
@ -1203,30 +1202,10 @@ static void remove_bg_job(struct pipe *pi)
prev_pipe->next = pi->next; prev_pipe->next = pi->next;
} }
free_pipe(pi); free_pipe(pi, 0);
free(pi); free(pi);
} }
/* free up all memory from a pipe */
static void free_pipe(struct pipe *pi)
{
int i;
for (i = 0; i < pi->num_progs; i++) {
free(pi->progs[i].argv);
if (pi->progs[i].redirects)
free(pi->progs[i].redirects);
}
if (pi->progs)
free(pi->progs);
if (pi->text)
free(pi->text);
if (pi->cmdbuf)
free(pi->cmdbuf);
memset(pi, 0, sizeof(struct pipe));
}
/* Checks to see if any background processes have exited -- if they /* Checks to see if any background processes have exited -- if they
have, figure out why and see if a job has completed */ have, figure out why and see if a job has completed */
static void checkjobs() static void checkjobs()
@ -1535,7 +1514,7 @@ static char *indenter(int i)
} }
/* return code is the exit status of the pipe */ /* return code is the exit status of the pipe */
static int run_pipe_test(struct pipe *pi, int indent) static int free_pipe(struct pipe *pi, int indent)
{ {
char **p; char **p;
struct child_prog *child; struct child_prog *child;
@ -1554,7 +1533,7 @@ static int run_pipe_test(struct pipe *pi, int indent)
child->argv=NULL; child->argv=NULL;
} else if (child->group) { } else if (child->group) {
final_printf("%s begin group (subshell:%d)\n",ind, child->subshell); final_printf("%s begin group (subshell:%d)\n",ind, child->subshell);
ret_code = run_list_test(child->group,indent+3); ret_code = free_pipe_list(child->group,indent+3);
final_printf("%s end group\n",ind); final_printf("%s end group\n",ind);
} else { } else {
final_printf("%s (nil)\n",ind); final_printf("%s (nil)\n",ind);
@ -1577,15 +1556,14 @@ static int run_pipe_test(struct pipe *pi, int indent)
return ret_code; return ret_code;
} }
static int run_list_test(struct pipe *head, int indent) static int free_pipe_list(struct pipe *head, int indent)
{ {
int rcode=0; /* if list has no members */ int rcode=0; /* if list has no members */
struct pipe *pi, *next; struct pipe *pi, *next;
char *ind = indenter(indent); char *ind = indenter(indent);
for (pi=head; pi; pi=next) { for (pi=head; pi; pi=next) {
if (pi->num_progs == 0) break;
final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode); final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode);
rcode = run_pipe_test(pi, indent); rcode = free_pipe(pi, indent);
final_printf("%s pipe followup code %d\n", ind, pi->followup); final_printf("%s pipe followup code %d\n", ind, pi->followup);
next=pi->next; next=pi->next;
pi->next=NULL; pi->next=NULL;
@ -1601,10 +1579,10 @@ static int run_list(struct pipe *pi)
if (fake_mode==0) { if (fake_mode==0) {
rcode = run_list_real(pi); rcode = run_list_real(pi);
} }
/* run_list_test has the side effect of clearing memory /* free_pipe_list has the side effect of clearing memory
* In the long run that function can be merged with run_list_real, * In the long run that function can be merged with run_list_real,
* but doing that now would hobble the debugging effort. */ * but doing that now would hobble the debugging effort. */
run_list_test(pi,0); free_pipe_list(pi,0);
return rcode; return rcode;
} }
@ -2142,7 +2120,7 @@ FILE *generate_stream_from_list(struct pipe *head)
pf = fdopen(channel[0],"r"); pf = fdopen(channel[0],"r");
debug_printf("pipe on FILE *%p\n",pf); debug_printf("pipe on FILE *%p\n",pf);
#else #else
run_list_test(head,0); free_pipe_list(head,0);
pf=popen("echo surrogate response","r"); pf=popen("echo surrogate response","r");
debug_printf("started fake pipe on FILE *%p\n",pf); debug_printf("started fake pipe on FILE *%p\n",pf);
#endif #endif

View File

@ -357,8 +357,8 @@ static void mark_closed(int fd);
static void close_all(); static void close_all();
/* "run" the final data structures: */ /* "run" the final data structures: */
static char *indenter(int i); static char *indenter(int i);
static int run_list_test(struct pipe *head, int indent); static int free_pipe_list(struct pipe *head, int indent);
static int run_pipe_test(struct pipe *pi, int indent); static int free_pipe(struct pipe *pi, int indent);
/* really run the final data structures: */ /* really run the final data structures: */
static int setup_redirects(struct child_prog *prog, int squirrel[]); static int setup_redirects(struct child_prog *prog, int squirrel[]);
static int pipe_wait(struct pipe *pi); static int pipe_wait(struct pipe *pi);
@ -395,7 +395,6 @@ static int parse_file_outer(FILE *f);
static void checkjobs(); static void checkjobs();
static void insert_bg_job(struct pipe *pi); static void insert_bg_job(struct pipe *pi);
static void remove_bg_job(struct pipe *pi); static void remove_bg_job(struct pipe *pi);
static void free_pipe(struct pipe *pi);
/* local variable support */ /* local variable support */
static char *get_local_var(const char *var); static char *get_local_var(const char *var);
static void unset_local_var(const char *name); static void unset_local_var(const char *name);
@ -1138,7 +1137,7 @@ static void pseudo_exec(struct child_prog *child)
debug_printf("runtime nesting to group\n"); debug_printf("runtime nesting to group\n");
interactive=0; /* crucial!!!! */ interactive=0; /* crucial!!!! */
rcode = run_list_real(child->group); rcode = run_list_real(child->group);
/* OK to leak memory by not calling run_list_test, /* OK to leak memory by not calling free_pipe_list,
* since this process is about to exit */ * since this process is about to exit */
_exit(rcode); _exit(rcode);
} else { } else {
@ -1203,30 +1202,10 @@ static void remove_bg_job(struct pipe *pi)
prev_pipe->next = pi->next; prev_pipe->next = pi->next;
} }
free_pipe(pi); free_pipe(pi, 0);
free(pi); free(pi);
} }
/* free up all memory from a pipe */
static void free_pipe(struct pipe *pi)
{
int i;
for (i = 0; i < pi->num_progs; i++) {
free(pi->progs[i].argv);
if (pi->progs[i].redirects)
free(pi->progs[i].redirects);
}
if (pi->progs)
free(pi->progs);
if (pi->text)
free(pi->text);
if (pi->cmdbuf)
free(pi->cmdbuf);
memset(pi, 0, sizeof(struct pipe));
}
/* Checks to see if any background processes have exited -- if they /* Checks to see if any background processes have exited -- if they
have, figure out why and see if a job has completed */ have, figure out why and see if a job has completed */
static void checkjobs() static void checkjobs()
@ -1535,7 +1514,7 @@ static char *indenter(int i)
} }
/* return code is the exit status of the pipe */ /* return code is the exit status of the pipe */
static int run_pipe_test(struct pipe *pi, int indent) static int free_pipe(struct pipe *pi, int indent)
{ {
char **p; char **p;
struct child_prog *child; struct child_prog *child;
@ -1554,7 +1533,7 @@ static int run_pipe_test(struct pipe *pi, int indent)
child->argv=NULL; child->argv=NULL;
} else if (child->group) { } else if (child->group) {
final_printf("%s begin group (subshell:%d)\n",ind, child->subshell); final_printf("%s begin group (subshell:%d)\n",ind, child->subshell);
ret_code = run_list_test(child->group,indent+3); ret_code = free_pipe_list(child->group,indent+3);
final_printf("%s end group\n",ind); final_printf("%s end group\n",ind);
} else { } else {
final_printf("%s (nil)\n",ind); final_printf("%s (nil)\n",ind);
@ -1577,15 +1556,14 @@ static int run_pipe_test(struct pipe *pi, int indent)
return ret_code; return ret_code;
} }
static int run_list_test(struct pipe *head, int indent) static int free_pipe_list(struct pipe *head, int indent)
{ {
int rcode=0; /* if list has no members */ int rcode=0; /* if list has no members */
struct pipe *pi, *next; struct pipe *pi, *next;
char *ind = indenter(indent); char *ind = indenter(indent);
for (pi=head; pi; pi=next) { for (pi=head; pi; pi=next) {
if (pi->num_progs == 0) break;
final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode); final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode);
rcode = run_pipe_test(pi, indent); rcode = free_pipe(pi, indent);
final_printf("%s pipe followup code %d\n", ind, pi->followup); final_printf("%s pipe followup code %d\n", ind, pi->followup);
next=pi->next; next=pi->next;
pi->next=NULL; pi->next=NULL;
@ -1601,10 +1579,10 @@ static int run_list(struct pipe *pi)
if (fake_mode==0) { if (fake_mode==0) {
rcode = run_list_real(pi); rcode = run_list_real(pi);
} }
/* run_list_test has the side effect of clearing memory /* free_pipe_list has the side effect of clearing memory
* In the long run that function can be merged with run_list_real, * In the long run that function can be merged with run_list_real,
* but doing that now would hobble the debugging effort. */ * but doing that now would hobble the debugging effort. */
run_list_test(pi,0); free_pipe_list(pi,0);
return rcode; return rcode;
} }
@ -2142,7 +2120,7 @@ FILE *generate_stream_from_list(struct pipe *head)
pf = fdopen(channel[0],"r"); pf = fdopen(channel[0],"r");
debug_printf("pipe on FILE *%p\n",pf); debug_printf("pipe on FILE *%p\n",pf);
#else #else
run_list_test(head,0); free_pipe_list(head,0);
pf=popen("echo surrogate response","r"); pf=popen("echo surrogate response","r");
debug_printf("started fake pipe on FILE *%p\n",pf); debug_printf("started fake pipe on FILE *%p\n",pf);
#endif #endif