/* Generic serial interface functions.
- Copyright (C) 1992-2014 Free Software Foundation, Inc.
+ Copyright (C) 1992-2017 Free Software Foundation, Inc.
This file is part of GDB.
#include "event-loop.h"
#include "gdb_select.h"
-#include <sys/time.h>
+#include "gdb_sys_time.h"
#ifdef USE_WIN32API
#include <winsock2.h>
#endif
static void
fd_event (int error, void *context)
{
- struct serial *scb = context;
+ struct serial *scb = (struct serial *) context;
if (error != 0)
{
scb->bufcnt = SERIAL_ERROR;
pull characters out of the buffer. See also
generic_readchar(). */
int nr;
- nr = scb->ops->read_prim (scb, BUFSIZ);
+
+ do
+ {
+ nr = scb->ops->read_prim (scb, BUFSIZ);
+ }
+ while (nr < 0 && errno == EINTR);
+
if (nr == 0)
{
scb->bufcnt = SERIAL_EOF;
static void
push_event (void *context)
{
- struct serial *scb = context;
+ struct serial *scb = (struct serial *) context;
scb->async_state = NOTHING_SCHEDULED; /* Timers are one-off */
run_async_handler_and_reschedule (scb);
/* Wait for input on scb, with timeout seconds. Returns 0 on success,
otherwise SERIAL_TIMEOUT or SERIAL_ERROR. */
+/* NOTE: Some of the code below is dead. The only possible values of
+ the TIMEOUT parameter are ONE and ZERO. OTOH, we should probably
+ get rid of the deprecated_ui_loop_hook call in do_ser_base_readchar
+ instead and support infinite time outs here. */
+
static int
ser_base_wait_for (struct serial *scb, int timeout)
{
int numfds;
struct timeval tv;
fd_set readfds, exceptfds;
+ int nfds;
/* NOTE: Some OS's can scramble the READFDS when the select()
call fails (ex the kernel with Red Hat 5.2). Initialize all
FD_SET (scb->fd, &readfds);
FD_SET (scb->fd, &exceptfds);
+ QUIT;
+
+ nfds = scb->fd + 1;
if (timeout >= 0)
- numfds = gdb_select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
+ numfds = interruptible_select (nfds, &readfds, 0, &exceptfds, &tv);
else
- numfds = gdb_select (scb->fd + 1, &readfds, 0, &exceptfds, 0);
+ numfds = interruptible_select (nfds, &readfds, 0, &exceptfds, 0);
if (numfds <= 0)
{
if (s == 0 && close_fd)
{
/* End of file. */
+ if (serial_is_async_p (scb))
+ delete_file_handler (scb->error_fd);
close (scb->error_fd);
scb->error_fd = -1;
break;
}
}
-/* Read a character with user-specified timeout. TIMEOUT is number of seconds
- to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
- char if successful. Returns -2 if timeout expired, EOF if line dropped
- dead, or -3 for any other error (see errno in that case). */
+/* Event-loop callback for a serial's error_fd. Flushes any error
+ output we might have. */
+
+static void
+handle_error_fd (int error, gdb_client_data client_data)
+{
+ serial *scb = (serial *) client_data;
+
+ ser_base_read_error_fd (scb, 0);
+}
+
+/* Read a character with user-specified timeout. TIMEOUT is number of
+ seconds to wait, or -1 to wait forever. Use timeout of 0 to effect
+ a poll. Returns char if successful. Returns SERIAL_TIMEOUT if
+ timeout expired, SERIAL_EOF if line dropped dead, or SERIAL_ERROR
+ for any other error (see errno in that case). */
static int
do_ser_base_readchar (struct serial *scb, int timeout)
if (status < 0)
return status;
- status = scb->ops->read_prim (scb, BUFSIZ);
+ do
+ {
+ status = scb->ops->read_prim (scb, BUFSIZ);
+ }
+ while (status < 0 && errno == EINTR);
if (status <= 0)
{
int
ser_base_write (struct serial *scb, const void *buf, size_t count)
{
- const char *str = buf;
+ const char *str = (const char *) buf;
int cc;
while (count > 0)
{
+ QUIT;
+
cc = scb->ops->write_prim (scb, str, count);
if (cc < 0)
- return 1;
+ {
+ if (errno == EINTR)
+ continue;
+ return 1;
+ }
count -= cc;
str += cc;
}
return 0; /* Never fails! */
}
+/* Implement the "setparity" serial_ops callback. */
+
+int
+ser_base_setparity (struct serial *scb, int parity)
+{
+ return 0; /* Never fails! */
+}
+
/* Put the SERIAL device into/out-of ASYNC mode. */
void
fprintf_unfiltered (gdb_stdlog, "[fd%d->asynchronous]\n",
scb->fd);
reschedule (scb);
+
+ if (scb->error_fd != -1)
+ add_file_handler (scb->error_fd, handle_error_fd, scb);
}
else
{
delete_timer (scb->async_state);
break;
}
+
+ if (scb->error_fd != -1)
+ delete_file_handler (scb->error_fd);
}
}