Fix child_results loop accessing after free()

This commit is contained in:
Themis Demetriades
2024-11-13 21:52:38 +00:00
parent 1368fa144a
commit 785f1a8d62

View File

@@ -47,6 +47,9 @@ struct process_start_data
tokens while maintaining state. */ tokens while maintaining state. */
char file_name[FNAME_MAX_LEN + 1]; /* Name of the file of the process to char file_name[FNAME_MAX_LEN + 1]; /* Name of the file of the process to
be started. */ be started. */
struct semaphore load_sema;
bool success;
}; };
static thread_func start_process NO_RETURN; static thread_func start_process NO_RETURN;
@@ -62,11 +65,7 @@ process_execute (const char *cmd)
char *cmd_copy; char *cmd_copy;
tid_t tid; tid_t tid;
struct process_start_data *data = malloc (sizeof (struct process_start_data)); struct process_start_data data;
if (data == NULL)
{
return TID_ERROR;
}
/* Make a copy of command. /* Make a copy of command.
Otherwise there's a race between the caller and load(). */ Otherwise there's a race between the caller and load(). */
@@ -80,7 +79,7 @@ process_execute (const char *cmd)
/* Retrieve first argument of command, which is the file name /* Retrieve first argument of command, which is the file name
of the process. */ of the process. */
char *file_name = strtok_r (cmd_copy, " ", &data->cmd_saveptr); char *file_name = strtok_r (cmd_copy, " ", &data.cmd_saveptr);
/* NOTE: Currently, the file being executed is closed in load () and then /* NOTE: Currently, the file being executed is closed in load () and then
reopened here. Because load is an exported public function, this reopened here. Because load is an exported public function, this
@@ -95,12 +94,24 @@ process_execute (const char *cmd)
/* Create a new thread to execute the command, by initializing /* Create a new thread to execute the command, by initializing
it running the function 'start_process' with the appropriate it running the function 'start_process' with the appropriate
arguments. For details of arguments, see 'start_process'. */ arguments. For details of arguments, see 'start_process'. */
data->cmd = cmd_copy; data.cmd = cmd_copy;
strlcpy (data->file_name, file_name, FNAME_MAX_LEN + 1); strlcpy (data.file_name, file_name, FNAME_MAX_LEN + 1);
sema_init (&data.load_sema, 0);
data.success = false;
tid = thread_create (file_name, PRI_DEFAULT, start_process, &data);
tid = thread_create (file_name, PRI_DEFAULT, start_process, data);
if (tid == TID_ERROR) if (tid == TID_ERROR)
palloc_free_page (cmd_copy); {
palloc_free_page (cmd_copy);
}
else
{
sema_down (&data.load_sema);
if (!data.success)
tid = TID_ERROR;
}
return tid; return tid;
} }
@@ -118,7 +129,6 @@ static void
start_process (void *proc_start_data) start_process (void *proc_start_data)
{ {
struct intr_frame if_; struct intr_frame if_;
bool success;
struct process_start_data *data = proc_start_data; struct process_start_data *data = proc_start_data;
@@ -136,21 +146,22 @@ start_process (void *proc_start_data)
file_deny_write (exec_file); file_deny_write (exec_file);
lock_release (&filesys_lock); lock_release (&filesys_lock);
success = load (data->file_name, &if_.eip, &if_.esp); data->success = load (data->file_name, &if_.eip, &if_.esp);
/* If load failed, free process startup data and quit. */ /* If load failed, free process startup data and quit. */
if (!success) if (!data->success)
{ {
palloc_free_page (data->cmd); palloc_free_page (data->cmd);
free (data); sema_up (&data->load_sema);
thread_exit (); thread_exit ();
} }
/* Initialize user process stack and free page used to store the /* Initialize user process stack and free page used to store the
command that executed the process. */ command that executed the process. */
success = process_init_stack (data->cmd_saveptr, &if_.esp, data->file_name); bool success = process_init_stack (data->cmd_saveptr, &if_.esp, data->file_name);
palloc_free_page (data->cmd); palloc_free_page (data->cmd);
free (data); data->success = success;
sema_up (&data->load_sema);
/* If stack initialization failed, free process resources and quit. */ /* If stack initialization failed, free process resources and quit. */
if (!success) if (!success)
@@ -297,7 +308,6 @@ process_wait (tid_t child_tid UNUSED)
} }
if (child_result == NULL) if (child_result == NULL)
{ {
printf ("-1 due to: child_result == NULL\n");
return -1; return -1;
} }
/* Wait for child to die. */ /* Wait for child to die. */
@@ -314,11 +324,6 @@ process_wait (tid_t child_tid UNUSED)
lock_release (&child_result->lock); lock_release (&child_result->lock);
free (child_result); free (child_result);
if (exit_status == -1)
{
printf ("-1 due to: child exit status wrong!\n");
}
return exit_status; return exit_status;
} }
@@ -327,16 +332,15 @@ void
process_exit (void) process_exit (void)
{ {
printf("(%d) EXIT STATUS: %d\n", thread_current ()->tid, thread_current ()->exit_status);
struct thread *cur = thread_current (); struct thread *cur = thread_current ();
uint32_t *pd; uint32_t *pd;
printf ("%s: exit(%d)\n", cur->name, cur->exit_status); printf ("%s: exit(%d)\n", cur->name, cur->exit_status);
if (cur->exec_file != NULL) if (cur->exec_file != NULL)
{ {
lock_acquire (&filesys_lock); lock_acquire (&filesys_lock);
file_allow_write (cur->exec_file);
file_close (cur->exec_file); file_close (cur->exec_file);
lock_release (&filesys_lock); lock_release (&filesys_lock);
} }
@@ -364,10 +368,11 @@ process_exit (void)
/* Free child process results or signal parent's death. */ /* Free child process results or signal parent's death. */
struct list_elem *e; struct list_elem *e;
for (e = list_begin (&cur->child_results); for (e = list_begin (&cur->child_results);
e != list_end (&cur->child_results); e = list_next (e)) e != list_end (&cur->child_results);)
{ {
struct process_result *result struct process_result *result
= list_entry (e, struct process_result, elem); = list_entry (e, struct process_result, elem);
struct list_elem *next = list_next (e);
lock_acquire (&result->lock); lock_acquire (&result->lock);
/* Child has died (and was not waited for). Free the result. */ /* Child has died (and was not waited for). Free the result. */
if (sema_try_down (&result->sema)) if (sema_try_down (&result->sema))
@@ -381,6 +386,7 @@ process_exit (void)
sema_up (&result->sema); sema_up (&result->sema);
lock_release (&result->lock); lock_release (&result->lock);
} }
e = next;
} }
/* Destroy the current process's page directory and switch back /* Destroy the current process's page directory and switch back