From 891661e8e5978859393b3c0518d256ccea9ef41d Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Mon, 11 Jun 2012 20:36:53 +0000 Subject: 2012-06-11 Pedro Alves * 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'. --- gdb/ser-base.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'gdb/ser-base.c') 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, -- cgit v1.2.1