From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18908 invoked by alias); 9 Oct 2009 01:53:49 -0000 Received: (qmail 18773 invoked by uid 22791); 9 Oct 2009 01:53:47 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=BAYES_00,SPF_FAIL X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 09 Oct 2009 01:53:44 +0000 Received: (qmail 24564 invoked from network); 9 Oct 2009 01:53:42 -0000 Received: from unknown (HELO orlando) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 9 Oct 2009 01:53:42 -0000 From: Pedro Alves To: gdb-patches@sourceware.org Subject: Make linux_nat.c's target_wait always respect TARGET_WNOHANG. Date: Fri, 09 Oct 2009 01:53:00 -0000 User-Agent: KMail/1.9.10 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200910090253.47934.pedro@codesourcery.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-10/txt/msg00190.txt.bz2 Moving from . This patch fixes an issue Hui noticed. linux_nat_wait_1 wasn't respecting the TARGET_WNOHANG option in the case of waiting for a specific lwpid. We have a related infrun bug. If gdb is thread hoping, or other situation when waiton_ptid is set (infwait_state != infwait_normal_state), a TARGET_WAITKIND_IGNORE would reset infwait_state and waiton_ptid. Tested on x86_64-unknown-linux-gnu native sync and async modes. I'm checking this in. Thanks Hui. -- Pedro Alves 2009-10-09 Pedro Alves * linux-nat.c (linux_nat_wait_1): Bail out, if TARGET_WNOHANG and we found no event while waiting for a specific LWP. * infrun.c (handle_inferior_event): Handle TARGET_WAITKIND_IGNORE before anything else. --- gdb/infrun.c | 62 +++++++++++++++++++++++++++----------------------------- gdb/linux-nat.c | 11 +++++++++ 2 files changed, 41 insertions(+), 32 deletions(-) Index: src/gdb/linux-nat.c =================================================================== --- src.orig/gdb/linux-nat.c 2009-10-09 02:23:48.000000000 +0100 +++ src/gdb/linux-nat.c 2009-10-09 02:42:37.000000000 +0100 @@ -3255,6 +3255,17 @@ retry: sigsuspend (&suspend_mask); } } + else if (target_options & TARGET_WNOHANG) + { + /* No interesting event for PID yet. */ + ourstatus->kind = TARGET_WAITKIND_IGNORE; + + if (debug_linux_nat_async) + fprintf_unfiltered (gdb_stdlog, "LLW: exit (ignore)\n"); + + restore_child_signals_mask (&prev_mask); + return minus_one_ptid; + } /* We shouldn't end up here unless we want to try again. */ gdb_assert (lp == NULL); Index: src/gdb/infrun.c =================================================================== --- src.orig/gdb/infrun.c 2009-10-09 02:23:48.000000000 +0100 +++ src/gdb/infrun.c 2009-10-09 02:52:29.000000000 +0100 @@ -2443,9 +2443,25 @@ handle_inferior_event (struct execution_ struct symtab_and_line stop_pc_sal; enum stop_kind stop_soon; + if (ecs->ws.kind == TARGET_WAITKIND_IGNORE) + { + /* We had an event in the inferior, but we are not interested in + handling it at this level. The lower layers have already + done what needs to be done, if anything. + + One of the possible circumstances for this is when the + inferior produces output for the console. The inferior has + not stopped, and we are ignoring the event. Another possible + circumstance is any event which the lower level knows will be + reported multiple times without an intervening resume. */ + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_IGNORE\n"); + prepare_to_wait (ecs); + return; + } + if (ecs->ws.kind != TARGET_WAITKIND_EXITED - && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED - && ecs->ws.kind != TARGET_WAITKIND_IGNORE) + && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED) { struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid)); gdb_assert (inf); @@ -2479,22 +2495,19 @@ handle_inferior_event (struct execution_ /* Dependent on the current PC value modified by adjust_pc_after_break. */ reinit_frame_cache (); - if (ecs->ws.kind != TARGET_WAITKIND_IGNORE) - { - breakpoint_retire_moribund (); + breakpoint_retire_moribund (); - /* Mark the non-executing threads accordingly. In all-stop, all - threads of all processes are stopped when we get any event - reported. In non-stop mode, only the event thread stops. If - we're handling a process exit in non-stop mode, there's - nothing to do, as threads of the dead process are gone, and - threads of any other process were left running. */ - if (!non_stop) - set_executing (minus_one_ptid, 0); - else if (ecs->ws.kind != TARGET_WAITKIND_SIGNALLED - && ecs->ws.kind != TARGET_WAITKIND_EXITED) - set_executing (inferior_ptid, 0); - } + /* Mark the non-executing threads accordingly. In all-stop, all + threads of all processes are stopped when we get any event + reported. In non-stop mode, only the event thread stops. If + we're handling a process exit in non-stop mode, there's nothing + to do, as threads of the dead process are gone, and threads of + any other process were left running. */ + if (!non_stop) + set_executing (minus_one_ptid, 0); + else if (ecs->ws.kind != TARGET_WAITKIND_SIGNALLED + && ecs->ws.kind != TARGET_WAITKIND_EXITED) + set_executing (inferior_ptid, 0); switch (infwait_state) { @@ -2777,21 +2790,6 @@ handle_inferior_event (struct execution_ print_stop_reason (NO_HISTORY, 0); stop_stepping (ecs); return; - - /* We had an event in the inferior, but we are not interested - in handling it at this level. The lower layers have already - done what needs to be done, if anything. - - One of the possible circumstances for this is when the - inferior produces output for the console. The inferior has - not stopped, and we are ignoring the event. Another possible - circumstance is any event which the lower level knows will be - reported multiple times without an intervening resume. */ - case TARGET_WAITKIND_IGNORE: - if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_IGNORE\n"); - prepare_to_wait (ecs); - return; } if (ecs->new_thread_event)