From ab17f7d67b2decbd8561977a47fec55a9e74337e Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Mon, 25 Jun 2007 19:04:12 +1000 Subject: [PATCH] - djm@cvs.openbsd.org 2007/06/19 02:04:43 [atomicio.c] if the fd passed to atomicio/atomiciov() is non blocking, then poll() to avoid a spin if it is not yet ready for reading/writing; ok dtucker@ --- ChangeLog | 6 +++++- atomicio.c | 24 ++++++++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 89e561800..07ee5e927 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,10 @@ when waiting for the multiplex exit status, read until the master end writes an entire int of data *and* closes the client_fd; fixes mux regression spotted by dtucker, ok dtucker@ + - djm@cvs.openbsd.org 2007/06/19 02:04:43 + [atomicio.c] + if the fd passed to atomicio/atomiciov() is non blocking, then poll() to + avoid a spin if it is not yet ready for reading/writing; ok dtucker@ 20070614 - (dtucker) [cipher-ctr.c umac.c openbsd-compat/openssl-compat.h] Move the @@ -3087,4 +3091,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4705 2007/06/25 08:59:17 dtucker Exp $ +$Id: ChangeLog,v 1.4706 2007/06/25 09:04:12 dtucker Exp $ diff --git a/atomicio.c b/atomicio.c index f651a292c..253139e99 100644 --- a/atomicio.c +++ b/atomicio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atomicio.c,v 1.23 2006/08/03 03:34:41 deraadt Exp $ */ +/* $OpenBSD: atomicio.c,v 1.24 2007/06/19 02:04:43 djm Exp $ */ /* * Copyright (c) 2006 Damien Miller. All rights reserved. * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. @@ -30,9 +30,11 @@ #include #include +#include #include #include +#include #include "atomicio.h" @@ -45,17 +47,24 @@ atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n) char *s = _s; size_t pos = 0; ssize_t res; + struct pollfd pfd; + pfd.fd = fd; + pfd.events = f == read ? POLLIN : POLLOUT; while (n > pos) { res = (f) (fd, s + pos, n - pos); switch (res) { case -1: #ifdef EWOULDBLOCK - if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) + if (errno == EINTR || errno == EWOULDBLOCK) #else - if (errno == EINTR || errno == EAGAIN) + if (errno == EINTR) #endif continue; + if (errno == EAGAIN) { + (void)poll(&pfd, 1, -1); + continue; + } return 0; case 0: errno = EPIPE; @@ -77,6 +86,7 @@ atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd, size_t pos = 0, rem; ssize_t res; struct iovec iov_array[IOV_MAX], *iov = iov_array; + struct pollfd pfd; if (iovcnt > IOV_MAX) { errno = EINVAL; @@ -85,12 +95,18 @@ atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd, /* Make a copy of the iov array because we may modify it below */ memcpy(iov, _iov, iovcnt * sizeof(*_iov)); + pfd.fd = fd; + pfd.events = f == readv ? POLLIN : POLLOUT; for (; iovcnt > 0 && iov[0].iov_len > 0;) { res = (f) (fd, iov, iovcnt); switch (res) { case -1: - if (errno == EINTR || errno == EAGAIN) + if (errno == EINTR) continue; + if (errno == EAGAIN) { + (void)poll(&pfd, 1, -1); + continue; + } return 0; case 0: errno = EPIPE;