This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
Re: Merge of nickrob-async-20060513 to mainline?
- From: Nick Roberts <nickrob at snap dot net dot nz>
- To: Daniel Jacobowitz <drow at false dot org>
- Cc: gdb at sources dot redhat dot com
- Date: Tue, 26 Sep 2006 20:38:23 +1200
- Subject: Re: Merge of nickrob-async-20060513 to mainline?
- References: <17652.63229.637451.185345@kahikatea.snap.net.nz> <20060830023335.GA6377@nevyn.them.org> <17653.930.196634.143646@kahikatea.snap.net.nz> <20060830040113.GA8257@nevyn.them.org> <17654.994.815362.897653@kahikatea.snap.net.nz> <20060830214257.GA5397@nevyn.them.org>
> > Instead of GDB waiting for the enferior to stop directly, it creates a
> > signal thread to do that. This means that the main thread can continue to
> > process the event loop. When the inferior does stop, the signal thread
> > writes to a file which GDB detects through handle_file_event in the event
> > loop. It then calls inferior_event_handler.
>
> OK, this is easily mimicable without threads, at least on GNU/Linux.
I'm starting to do this now. I still use a pipe to write to a file descriptor
but instead of a separate thread I use a while loop in gdb_wait_for_event.
I've only done it for select because that's all I know but I guess a similar
thing could be done for poll. It seems to work reasonably well for single
threaded inferiors but get's stuck again with multi-threaded ones. The
multi-threaded code in linux-nat.c just seems so convoluted (maybe threads
are more easily handled with a Mach kernel).
Below is a (pseudo) diff fragment that should (hopefully) give the general
idea. Do you mean something along these lines? If yes, I'll try to get it
to work more generally.
--
Nick http://www.inet.net.nz/~nickrob
*** linux-nat.c 18 Sep 2006 16:44:40 +1200 1.50
+ static int gdb_fetch_event (int* ptr_status)
+ {
+ struct timeval tv;
+ fd_set fds;
+ int msg[2], ret;
+
+ FD_ZERO (&fds);
+ FD_SET (gdb_status[0], &fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ msg[0] = 0;
+ ret = select (FD_SETSIZE, &fds, NULL, NULL, NULL);
+ if (ret)
+ {
+ read (gdb_status[0], msg, 2*sizeof (int));
+ *ptr_status = msg[1];
+ }
+
+ return msg[0];
+ }
+
static ptid_t
linux_nat_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
***************
*** 1956,1962 **** (linux_nat_wait)
{
pid_t lwpid;
! lwpid = my_waitpid (pid, &status, options);
if (lwpid > 0)
{
gdb_assert (pid == -1 || lwpid == pid);
--- 2094,2106 ----
{
pid_t lwpid;
! if (target_can_async_p () && gdb_post_startup)
! {
! gdb_file_event = 0;
! lwpid = gdb_fetch_event (&status);
! }
! else
! lwpid = my_waitpid (pid, &status, options);
if (lwpid > 0)
{
gdb_assert (pid == -1 || lwpid == pid);
*** event-loop.c (gdb_wait_for_event) 11 Feb 2006 11:01:43 +1300 1.29
gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0];
gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1];
gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2];
! num_found = gdb_select (gdb_notifier.num_fds,
! &gdb_notifier.ready_masks[0],
! &gdb_notifier.ready_masks[1],
! &gdb_notifier.ready_masks[2],
! gdb_notifier.timeout_valid
! ? &gdb_notifier.select_timeout : NULL);
/* Clear the masks after an error from select. */
if (num_found == -1)
--- 765,806 ----
gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0];
gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1];
gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2];
!
! if (event_loop_p)
! {
! struct timeval tv;
!
! while (num_found == 0)
! {
! msg[0] = waitpid (-1, ptr_status, WNOHANG);
!
! if (msg[0] > 0)
! {
! msg[1] = *ptr_status;
! write (gdb_status[1], msg, 2*sizeof (int));
! gdb_file_event = 1;
! }
!
! tv.tv_sec = 0;
! tv.tv_usec = 1000;
!
! gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0];
! gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1];
! gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2];
!
! num_found = gdb_select (gdb_notifier.num_fds,
! &gdb_notifier.ready_masks[0],
! &gdb_notifier.ready_masks[1],
! &gdb_notifier.ready_masks[2],
! &tv);
! }
! } else
! num_found = gdb_select (gdb_notifier.num_fds,
! &gdb_notifier.ready_masks[0],
! &gdb_notifier.ready_masks[1],
! &gdb_notifier.ready_masks[2],
! gdb_notifier.timeout_valid
! ? &gdb_notifier.select_timeout : NULL);