From: Ben Pfaff Date: Fri, 11 Jan 2013 01:22:24 +0000 (-0800) Subject: worker: Do not use poll_block() in worker_send_iovec(). X-Git-Tag: sliver-openvswitch-1.9.90-3~10^2~11 X-Git-Url: http://git.onelab.eu/?p=sliver-openvswitch.git;a=commitdiff_plain;h=df7a5a97f07783cddad373ea69cbab1a0876e426 worker: Do not use poll_block() in worker_send_iovec(). The following call stack was possible: poll_block() -> vlog -> worker_send_iovec() -> poll_block() which caused corruption because poll_block() is not reentrant. Bug #14616. Signed-off-by: Ben Pfaff Acked-by: Ethan Jackson --- diff --git a/lib/worker.c b/lib/worker.c index f2b896e88..b281d70b7 100644 --- a/lib/worker.c +++ b/lib/worker.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Nicira, Inc. +/* Copyright (c) 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -198,6 +198,7 @@ worker_send_iovec(const struct iovec iovs[], size_t n_iovs, size_t sent = 0; for (;;) { + struct pollfd pfd; int error; /* Try to send the rest of the request. */ @@ -210,8 +211,21 @@ worker_send_iovec(const struct iovec iovs[], size_t n_iovs, /* Process replies to avoid deadlock. */ worker_run(); - poll_fd_wait(client_sock, POLLIN | POLLOUT); - poll_block(); + /* Wait for 'client_sock' to become ready before trying again. We + * can't use poll_block() because it sometimes calls into vlog, which + * calls indirectly into worker_send_iovec(). To be usable here, + * poll_block() would therefore need to be reentrant, but it isn't + * (calling it recursively causes memory corruption and an eventual + * crash). */ + pfd.fd = client_sock; + pfd.events = POLLIN | POLLOUT; + do { + error = poll(&pfd, 1, -1) < 0 ? errno : 0; + } while (error == EINTR); + if (error) { + worker_broke(); + VLOG_ABORT("poll failed (%s)", strerror(error)); + } } }