diff options
author | Tristan Gingold <tristan.gingold@adacore.com> | 2014-04-09 10:23:19 +0200 |
---|---|---|
committer | Tristan Gingold <tristan.gingold@adacore.com> | 2014-04-09 10:23:19 +0200 |
commit | 15a9128a964499b78bd70ef3d2dc73edce56d825 (patch) | |
tree | 412d7e3af2e7b6a8793bf97065b9eeaa9f9323c4 /gdb/darwin-nat.c | |
parent | 19e1c431f72007f8a7a6a8e8b2511c74f3e8a000 (diff) | |
download | gdb-15a9128a964499b78bd70ef3d2dc73edce56d825.zip gdb-15a9128a964499b78bd70ef3d2dc73edce56d825.tar.gz gdb-15a9128a964499b78bd70ef3d2dc73edce56d825.tar.bz2 |
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.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c index 6f9a64a..0ffa69a 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; |