summaryrefslogtreecommitdiff
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
commit891661e8e5978859393b3c0518d256ccea9ef41d (patch)
tree175915f3e2f821feafd7e8ce32917e0afb2dbf91 /gdb/ser-base.c
parent877dce5b0d75d33cf93a4cda88a73cf828be5875 (diff)
downloadgdb-891661e8e5978859393b3c0518d256ccea9ef41d.tar.gz
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 b4399d0c4ba..2f12dfcdc17 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,