[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Lost] [Patch] Fix für Panic in RPC-Rücksprung nach destroy_task
Diese Patch fixt hoffentlich das folgende Problem:
// FIXME Wenn der zu beendende Task kurz vorher einen RPC gemacht
// hat der aufgerufene Prozess den jetzt beendeten Task in
// callee->rpcs, beim Rücksprung gibt es einen Panic, weil den Speicher
// mittlerweile gefreet wurde
Index: src/kernel/include/rpc.h
===================================================================
--- src/kernel/include/rpc.h (Revision 583)
+++ src/kernel/include/rpc.h (Arbeitskopie)
@@ -10,5 +10,6 @@
dword data_size, void* data, byte irq);
void return_from_rpc(struct int_stack_frame ** esp);
+void rpc_destroy_task_backlinks(struct task* destroyed_task);
#endif
Index: src/kernel/src/task.c
===================================================================
--- src/kernel/src/task.c (Revision 595)
+++ src/kernel/src/task.c (Arbeitskopie)
@@ -312,10 +312,10 @@
free((char*) task_ptr->cmdline);
}
- // FIXME Wenn der zu beendende Task kurz vorher einen RPC gemacht hat,
+ // Wenn der zu beendende Task kurz vorher einen RPC gemacht hat,
// hat der aufgerufene Prozess den jetzt beendeten Task in
- // callee->rpcs, beim Rücksprung gibt es einen Panic, weil den Speicher
- // mittlerweile gefreet wurde
+ // callee->rpcs und der Ruecksprung wurde im Desaster enden.
+ rpc_destroy_task_backlinks(task_ptr);
// Pagedir des tasks mappen, um den gesamten Speicher
// freigeben zu können
Index: src/kernel/src/rpc.c
===================================================================
--- src/kernel/src/rpc.c (Revision 583)
+++ src/kernel/src/rpc.c (Arbeitskopie)
@@ -305,7 +305,9 @@
callee_isf->eflags = rpc->eflags;
// Wechsel zum aufrufenden Task
- schedule_to_task(rpc->caller, (dword*) esp);
+ if (rpc->caller) {
+ schedule_to_task(rpc->caller, (dword*) esp);
+ }
// Wenn es ein IRQ-verarbeitender RPC war, den Interrupt jetzt
// wieder aktivieren
@@ -316,3 +318,24 @@
free(rpc);
}
+
+/**
+ * Entfernt den gegebenen Task aus allen RPC-Backlinks.
+ *
+ * Diese Funktion wird benoetigt, wenn ein Task einen RPC aufruft und beendet
+ * wird, bevor der RPC fertig ist. Ansonsten zeigt rpc->caller ins Leere,
+ * was in return_from_rpc() zur Katastrophe führt.
+ */
+void rpc_destroy_task_backlinks(struct task* destroyed_task)
+{
+ struct task* task;
+ for (task = first_task; task != NULL; task = task->next_task) {
+ int i;
+ rpc_t* rpc;
+ for (i = 0; (rpc = list_get_element_at(task->rpcs, i)); i++) {
+ if (rpc->caller == destroyed_task) {
+ rpc->caller = NULL;
+ }
+ }
+ }
+}