diff options
author | Da Zheng <zhengda1936@gmail.com> | 2012-07-01 01:07:50 -0300 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2012-07-01 01:07:50 -0300 |
commit | ccbbdf63102a21e755cd17f68f6d8c43beda21ef (patch) | |
tree | 7bc7f9438afa6977c6496397c0a24dcf6ebb77ef /utils/rpctrace.c | |
parent | a5f023c7e7e58583dedfd9a172efe9ef02429048 (diff) |
Make rpctrace handle terminate/suspend signals correctly
Fixes bug #3939
* rpctrace.c (traced_task): Relocate.
(wrap_all_threads): New function.
(wrap_new_thread): Likewise.
(trace_and_forward): Wrap all thread ports.
Diffstat (limited to 'utils/rpctrace.c')
-rw-r--r-- | utils/rpctrace.c | 88 |
1 files changed, 86 insertions, 2 deletions
diff --git a/utils/rpctrace.c b/utils/rpctrace.c index 996d4bae..24e20c4e 100644 --- a/utils/rpctrace.c +++ b/utils/rpctrace.c @@ -85,6 +85,8 @@ msgid_ihash_cleanup (void *element, void *arg) static struct hurd_ihash msgid_ihash = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP); +task_t traced_task; + /* Parse a file of RPC names and message IDs as output by mig's -list option: "subsystem base-id routine n request-id reply-id". Put each request-id value into `msgid_ihash' with the routine name as its value. */ @@ -647,6 +649,82 @@ print_contents (mach_msg_header_t *inp, } } +/* Wrap all thread port in the task */ +static void +wrap_all_threads (task_t task) +{ + struct traced_info *thread_send_wrapper; + thread_t *threads; + size_t nthreads; + error_t err; + + err = task_threads (task, &threads, &nthreads); + if (err) + error (2, err, "task_threads"); + + for (int i = 0; i < nthreads; ++i) + { + thread_send_wrapper = hurd_ihash_find (&traced_names, threads[i]); + /* We haven't seen the port. */ + if (thread_send_wrapper == NULL) + { + mach_port_t new_thread_port; + thread_send_wrapper = new_send_wrapper (threads[i], &new_thread_port); + free (thread_send_wrapper->name); + asprintf (&thread_send_wrapper->name, "thread%d", threads[i]); + + err = mach_port_insert_right (mach_task_self (), + new_thread_port, new_thread_port, + MACH_MSG_TYPE_MAKE_SEND); + if (err) + error (2, err, "mach_port_insert_right"); + + err = thread_set_kernel_port (threads[i], new_thread_port); + if (err) + error (2, err, "thread_set_kernel_port"); + + mach_port_deallocate (mach_task_self (), new_thread_port); + } + } + vm_deallocate (mach_task_self (), threads, nthreads * sizeof (thread_t)); +} + +/* Wrap the new thread port that is in the message. */ +static void +wrap_new_thread (mach_msg_header_t *inp) +{ + error_t err; + mach_port_t thread_port; + struct + { + mach_msg_header_t head; + mach_msg_type_t retcode_type; + kern_return_t retcode; + mach_msg_type_t child_thread_type; + mach_port_t child_thread; + } *reply = (void *) inp; + /* This function is called after rewrite_right, + * so the wrapper for the thread port has been created. */ + struct traced_info *send_wrapper = ports_lookup_port (traced_bucket, + reply->child_thread, 0); + + assert (send_wrapper); + thread_port = send_wrapper->forward; + + err = mach_port_insert_right (mach_task_self (), reply->child_thread, + reply->child_thread, MACH_MSG_TYPE_MAKE_SEND); + if (err) + error (2, err, "mach_port_insert_right"); + err = thread_set_kernel_port (thread_port, reply->child_thread); + if (err) + error (2, err, "thread_set_kernel_port"); + mach_port_deallocate (mach_task_self (), reply->child_thread); + + free (send_wrapper->name); + asprintf (&send_wrapper->name, "thread%d", thread_port); + ports_port_deref (send_wrapper); +} + int trace_and_forward (mach_msg_header_t *inp, mach_msg_header_t *outp) { @@ -775,6 +853,9 @@ trace_and_forward (mach_msg_header_t *inp, mach_msg_header_t *outp) putc (' ', ostream); print_contents (&rh->Head, rh + 1); putc ('\n', ostream); + + if (inp->msgh_id == 2161)/* the reply message for thread_create */ + wrap_new_thread (inp); } else { @@ -786,6 +867,11 @@ trace_and_forward (mach_msg_header_t *inp, mach_msg_header_t *outp) else /* Leave a partial line that will be finished later. */ fprintf (ostream, ")"); + + /* If it's the request of exec_startup_get_info, + * it means that the traced process starts to run */ + if (inp->msgh_id == 30500) + wrap_all_threads (traced_task); } } @@ -1021,8 +1107,6 @@ print_data (mach_msg_type_name_t type, /*** Main program and child startup ***/ -task_t traced_task; - /* Run a child and have it do more or else `execvpe (argv, envp);'. */ pid_t |