aboutsummaryrefslogtreecommitdiff
path: root/gdb/ser-base.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2012-06-11 20:36:53 +0000
committerPedro Alves <palves@redhat.com>2012-06-11 20:36:53 +0000
commitddefb60ff89becf2b18d0cf7930358320c6ec0e6 (patch)
tree88f0794b9680f0b82c2def63d8ebb4794c309b58 /gdb/ser-base.c
parentd5ad6aa5ce9ef3812c344bfebfb27bda36d8cb46 (diff)
downloadgdb-ddefb60ff89becf2b18d0cf7930358320c6ec0e6.zip
gdb-ddefb60ff89becf2b18d0cf7930358320c6ec0e6.tar.gz
gdb-ddefb60ff89becf2b18d0cf7930358320c6ec0e6.tar.bz2
2012-06-11 Pedro Alves <palves@redhat.com>
* ser-base.c (run_async_handler_and_reschedule): New. (fd_event, push_event): Use it. * serial.c (serial_open, serial_fdopen_ops): Set the initial reference count to 1. (do_serial_close): Set the bufp field to NULL. Use serial_unref instead of xfree. (serial_is_open, serial_ref, serial_unref): New. * serial.h (serial_open): Adjust comment. (serial_is_open): Declare. (serial_close): Adjust comment. (serial_ref, serial_unref) Declare. (struct serial): New field 'refcnt'.
Diffstat (limited to 'gdb/ser-base.c')
-rw-r--r--gdb/ser-base.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/gdb/ser-base.c b/gdb/ser-base.c
index b4399d0..2f12dfc 100644
--- a/gdb/ser-base.c
+++ b/gdb/ser-base.c
@@ -123,6 +123,29 @@ reschedule (struct serial *scb)
}
}
+/* Run the SCB's async handle, and reschedule, if the handler doesn't
+ close SCB. */
+
+static void
+run_async_handler_and_reschedule (struct serial *scb)
+{
+ int is_open;
+
+ /* Take a reference, so a serial_close call within the handler
+ doesn't make SCB a dangling pointer. */
+ serial_ref (scb);
+
+ /* Run the handler. */
+ scb->async_handler (scb, scb->async_context);
+
+ is_open = serial_is_open (scb);
+ serial_unref (scb);
+
+ /* Get ready for more, if not already closed. */
+ if (is_open)
+ reschedule (scb);
+}
+
/* FD_EVENT: This is scheduled when the input FIFO is empty (and there
is no pending error). As soon as data arrives, it is read into the
input FIFO and the client notified. The client should then drain
@@ -158,8 +181,7 @@ fd_event (int error, void *context)
scb->bufcnt = SERIAL_ERROR;
}
}
- scb->async_handler (scb, scb->async_context);
- reschedule (scb);
+ run_async_handler_and_reschedule (scb);
}
/* PUSH_EVENT: The input FIFO is non-empty (or there is a pending
@@ -173,9 +195,7 @@ push_event (void *context)
struct serial *scb = context;
scb->async_state = NOTHING_SCHEDULED; /* Timers are one-off */
- scb->async_handler (scb, scb->async_context);
- /* re-schedule */
- reschedule (scb);
+ run_async_handler_and_reschedule (scb);
}
/* Wait for input on scb, with timeout seconds. Returns 0 on success,