summaryrefslogtreecommitdiff
path: root/gdb/darwin-nat.c
diff options
context:
space:
mode:
authorTristan Gingold <tristan.gingold@adacore.com>2014-04-09 10:23:19 +0200
committerTristan Gingold <tristan.gingold@adacore.com>2014-04-09 10:23:19 +0200
commit15a9128a964499b78bd70ef3d2dc73edce56d825 (patch)
tree412d7e3af2e7b6a8793bf97065b9eeaa9f9323c4 /gdb/darwin-nat.c
parent19e1c431f72007f8a7a6a8e8b2511c74f3e8a000 (diff)
darwin: fix thinko (free thread port after threads are discovered).
Due to a thinko, a message could be not understood and ignored. The result was a dead-lock (gdb is waiting for an event that never happen). The port of the thread was deallocated before new threads are discovered. As a consequence, the origin of the message was unknown (instead of being linked to the newly created thread). gdb/ * darwin-nat.c (darwin_check_new_threads): Fix port leak, add comments. (darwin_decode_exception_message): Free port only after use.
Diffstat (limited to 'gdb/darwin-nat.c')
-rw-r--r--gdb/darwin-nat.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c
index 6f9a64a545..0ffa69aacd 100644
--- a/gdb/darwin-nat.c
+++ b/gdb/darwin-nat.c
@@ -303,9 +303,18 @@ darwin_check_new_threads (struct inferior *inf)
break;
if (i == new_nbr)
{
+ /* Deallocate ports. */
+ for (i = 0; i < new_nbr; i++)
+ {
+ kret = mach_port_deallocate (mach_task_self (), thread_list[i]);
+ MACH_CHECK_ERROR (kret);
+ }
+
+ /* Deallocate the buffer. */
kret = vm_deallocate (gdb_task, (vm_address_t) thread_list,
new_nbr * sizeof (int));
MACH_CHECK_ERROR (kret);
+
return;
}
}
@@ -331,8 +340,10 @@ darwin_check_new_threads (struct inferior *inf)
new_ix++;
old_ix++;
- kret = mach_port_deallocate (gdb_task, old_id);
+ /* Deallocate the port. */
+ kret = mach_port_deallocate (gdb_task, new_id);
MACH_CHECK_ERROR (kret);
+
continue;
}
if (new_ix < new_nbr && new_id == MACH_PORT_DEAD)
@@ -382,6 +393,7 @@ darwin_check_new_threads (struct inferior *inf)
VEC_free (darwin_thread_t, darwin_inf->threads);
darwin_inf->threads = thread_vec;
+ /* Deallocate the buffer. */
kret = vm_deallocate (gdb_task, (vm_address_t) thread_list,
new_nbr * sizeof (int));
MACH_CHECK_ERROR (kret);
@@ -594,11 +606,10 @@ darwin_decode_exception_message (mach_msg_header_t *hdr,
task_port = desc[1].name;
thread_port = desc[0].name;
- /* We got new rights to the task and the thread. Get rid of them. */
+ /* We got new rights to the task, get rid of it. Do not get rid of thread
+ right, as we will need it to find the thread. */
kret = mach_port_deallocate (mach_task_self (), task_port);
MACH_CHECK_ERROR (kret);
- kret = mach_port_deallocate (mach_task_self (), thread_port);
- MACH_CHECK_ERROR (kret);
/* Find process by port. */
inf = darwin_find_inferior_by_task (task_port);
@@ -611,6 +622,10 @@ darwin_decode_exception_message (mach_msg_header_t *hdr,
kern_return_t kret;
mig_reply_error_t reply;
+ /* Free thread port (we don't know it). */
+ kret = mach_port_deallocate (mach_task_self (), thread_port);
+ MACH_CHECK_ERROR (kret);
+
darwin_encode_reply (&reply, hdr, KERN_SUCCESS);
kret = mach_msg (&reply.Head, MACH_SEND_MSG | MACH_SEND_INTERRUPT,
@@ -627,6 +642,11 @@ darwin_decode_exception_message (mach_msg_header_t *hdr,
message can be deallocated. */
darwin_check_new_threads (inf);
+ /* Free the thread port (as gdb knows the thread, it has already has a right
+ for it, so this just decrement a reference counter). */
+ kret = mach_port_deallocate (mach_task_self (), thread_port);
+ MACH_CHECK_ERROR (kret);
+
thread = darwin_find_thread (inf, thread_port);
if (thread == NULL)
return -1;