summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2008-11-21 12:59:03 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2008-11-21 12:59:03 +0100
commite00115904ff7c1854957117d52a6db484050965b (patch)
tree1fd6c4fea920ebe96634ad0775772545256a8f75 /client
parent44711e0ca2658da080e04ce7e208a78c9b20e927 (diff)
birdc died during terminal resize because of unhandled EINTR
in select loop.
Diffstat (limited to 'client')
-rw-r--r--client/client.c61
1 files changed, 48 insertions, 13 deletions
diff --git a/client/client.c b/client/client.c
index e3f539e1..905526a4 100644
--- a/client/client.c
+++ b/client/client.c
@@ -298,11 +298,18 @@ server_read(void)
int c;
byte *start, *p;
+ redo:
c = read(server_fd, server_read_pos, server_read_buf + sizeof(server_read_buf) - server_read_pos);
if (!c)
die("Connection closed by server.");
if (c < 0)
- die("Server read error: %m");
+ {
+ if (errno == EINTR)
+ goto redo;
+ else
+ die("Server read error: %m");
+ }
+
start = server_read_buf;
p = server_read_pos;
server_read_pos += c;
@@ -331,6 +338,7 @@ static fd_set select_fds;
static void
select_loop(int mode)
{
+ int rv;
server_reply = -1;
while (mode || server_reply < 0)
{
@@ -338,7 +346,16 @@ select_loop(int mode)
FD_SET(server_fd, &select_fds);
if (mode)
FD_SET(0, &select_fds);
- select(server_fd+1, &select_fds, NULL, NULL, NULL);
+
+ rv = select(server_fd+1, &select_fds, NULL, NULL, NULL);
+ if (rv < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ else
+ die("select: %m");
+ }
+
if (FD_ISSET(server_fd, &select_fds))
{
server_read();
@@ -352,6 +369,30 @@ select_loop(int mode)
}
static void
+wait_for_write(int fd)
+{
+ while (1)
+ {
+ int rv;
+ fd_set set;
+ FD_ZERO(&set);
+ FD_SET(fd, &set);
+
+ rv = select(fd+1, NULL, &set, NULL, NULL);
+ if (rv < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ else
+ die("select: %m");
+ }
+
+ if (FD_ISSET(server_fd, &set))
+ return;
+ }
+}
+
+static void
server_send(char *cmd)
{
int l = strlen(cmd);
@@ -362,19 +403,13 @@ server_send(char *cmd)
while (l)
{
int cnt = write(server_fd, z, l);
+
if (cnt < 0)
{
- if (errno == -EAGAIN)
- {
- fd_set set;
- FD_ZERO(&set);
- do
- {
- FD_SET(server_fd, &set);
- select(server_fd+1, NULL, &set, NULL, NULL);
- }
- while (!FD_ISSET(server_fd, &set));
- }
+ if (errno == EAGAIN)
+ wait_for_write(server_fd);
+ else if (errno == EINTR)
+ continue;
else
die("Server write error: %m");
}