diff options
-rw-r--r-- | lib/stream.c | 26 | ||||
-rw-r--r-- | lib/stream.h | 2 | ||||
-rw-r--r-- | lib/unixctl.c | 2 | ||||
-rw-r--r-- | ovsdb/ovsdb-client.c | 2 | ||||
-rw-r--r-- | python/ovs/stream.py | 16 | ||||
-rw-r--r-- | tests/test-jsonrpc.c | 4 | ||||
-rw-r--r-- | tests/test-ovsdb.c | 2 | ||||
-rw-r--r-- | tests/test-ovsdb.py | 2 | ||||
-rw-r--r-- | tests/test-stream.c | 2 | ||||
-rw-r--r-- | tests/test-stream.py | 2 |
10 files changed, 41 insertions, 19 deletions
diff --git a/lib/stream.c b/lib/stream.c index c4dabda39..e246b3773 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -241,27 +241,39 @@ error: } /* Blocks until a previously started stream connection attempt succeeds or - * fails. 'error' should be the value returned by stream_open() and 'streamp' - * should point to the stream pointer set by stream_open(). Returns 0 if - * successful, otherwise a positive errno value other than EAGAIN or - * EINPROGRESS. If successful, leaves '*streamp' untouched; on error, closes - * '*streamp' and sets '*streamp' to null. + * fails, but no more than 'timeout' milliseconds. 'error' should be the + * value returned by stream_open() and 'streamp' should point to the stream + * pointer set by stream_open(). Returns 0 if successful, otherwise a + * positive errno value other than EAGAIN or EINPROGRESS. If successful, + * leaves '*streamp' untouched; on error, closes '*streamp' and sets + * '*streamp' to null. Negative value of 'timeout' means infinite waiting. * * Typical usage: - * error = stream_open_block(stream_open("tcp:1.2.3.4:5", &stream), &stream); + * error = stream_open_block(stream_open("tcp:1.2.3.4:5", &stream), -1, + * &stream); */ int -stream_open_block(int error, struct stream **streamp) +stream_open_block(int error, long long int timeout, struct stream **streamp) { struct stream *stream = *streamp; fatal_signal_run(); if (!error) { + long long int deadline = (timeout >= 0 + ? time_msec() + timeout + : LLONG_MAX); while ((error = stream_connect(stream)) == EAGAIN) { + if (deadline != LLONG_MAX && time_msec() > deadline) { + error = ETIMEDOUT; + break; + } stream_run(stream); stream_run_wait(stream); stream_connect_wait(stream); + if (deadline != LLONG_MAX) { + poll_timer_wait_until(deadline); + } poll_block(); } ovs_assert(error != EINPROGRESS); diff --git a/lib/stream.h b/lib/stream.h index 88f576155..77bffa498 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -34,7 +34,7 @@ void stream_usage(const char *name, bool active, bool passive, bool bootstrap); /* Bidirectional byte streams. */ int stream_verify_name(const char *name); int stream_open(const char *name, struct stream **, uint8_t dscp); -int stream_open_block(int error, struct stream **); +int stream_open_block(int error, long long int timeout, struct stream **); void stream_close(struct stream *); const char *stream_get_name(const struct stream *); int stream_connect(struct stream *); diff --git a/lib/unixctl.c b/lib/unixctl.c index 0bcfada91..c216de3d0 100644 --- a/lib/unixctl.c +++ b/lib/unixctl.c @@ -460,7 +460,7 @@ unixctl_client_create(const char *path, struct jsonrpc **client) *client = NULL; error = stream_open_block(stream_open(unix_path, &stream, DSCP_DEFAULT), - &stream); + -1, &stream); free(unix_path); free(abs_path); diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c index 7c8a59d0e..83c3c12cc 100644 --- a/ovsdb/ovsdb-client.c +++ b/ovsdb/ovsdb-client.c @@ -498,7 +498,7 @@ open_jsonrpc(const char *server) int error; error = stream_open_block(jsonrpc_stream_open(server, &stream, - DSCP_DEFAULT), &stream); + DSCP_DEFAULT), -1, &stream); if (error == EAFNOSUPPORT) { struct pstream *pstream; diff --git a/python/ovs/stream.py b/python/ovs/stream.py index cdfcc399e..da683afd8 100644 --- a/python/ovs/stream.py +++ b/python/ovs/stream.py @@ -206,10 +206,12 @@ class Stream(object): raise NotImplementedError("This method must be overrided by subclass") @staticmethod - def open_block(error_stream): + def open_block(error_stream, timeout=None): """Blocks until a Stream completes its connection attempt, either - succeeding or failing. (error, stream) should be the tuple returned by - Stream.open(). Returns a tuple of the same form. + succeeding or failing, but no more than 'timeout' milliseconds. + (error, stream) should be the tuple returned by Stream.open(). + Negative value of 'timeout' means infinite waiting. + Returns a tuple of the same form. Typical usage: error, stream = Stream.open_block(Stream.open("unix:/tmp/socket"))""" @@ -217,6 +219,9 @@ class Stream(object): # Py3 doesn't support tuple parameter unpacking - PEP 3113 error, stream = error_stream if not error: + deadline = None + if timeout is not None and timeout >= 0: + deadline = ovs.timeval.msec() + timeout while True: error = stream.connect() if sys.platform == 'win32' and error == errno.WSAEWOULDBLOCK: @@ -225,10 +230,15 @@ class Stream(object): error = errno.EAGAIN if error != errno.EAGAIN: break + if deadline is not None and ovs.timeval.msec() > deadline: + error = errno.ETIMEDOUT + break stream.run() poller = ovs.poller.Poller() stream.run_wait(poller) stream.connect_wait(poller) + if deadline is not None: + poller.timer_wait_until(deadline) poller.block() if stream.socket is not None: assert error != errno.EINPROGRESS diff --git a/tests/test-jsonrpc.c b/tests/test-jsonrpc.c index 49d2b91bd..04e941b14 100644 --- a/tests/test-jsonrpc.c +++ b/tests/test-jsonrpc.c @@ -272,7 +272,7 @@ do_request(struct ovs_cmdl_context *ctx) } error = stream_open_block(jsonrpc_stream_open(ctx->argv[1], &stream, - DSCP_DEFAULT), &stream); + DSCP_DEFAULT), -1, &stream); if (error) { ovs_fatal(error, "could not open \"%s\"", ctx->argv[1]); } @@ -312,7 +312,7 @@ do_notify(struct ovs_cmdl_context *ctx) } error = stream_open_block(jsonrpc_stream_open(ctx->argv[1], &stream, - DSCP_DEFAULT), &stream); + DSCP_DEFAULT), -1, &stream); if (error) { ovs_fatal(error, "could not open \"%s\"", ctx->argv[1]); } diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c index 453d88eab..187eb2867 100644 --- a/tests/test-ovsdb.c +++ b/tests/test-ovsdb.c @@ -2416,7 +2416,7 @@ do_idl(struct ovs_cmdl_context *ctx) struct stream *stream; error = stream_open_block(jsonrpc_stream_open(ctx->argv[1], &stream, - DSCP_DEFAULT), &stream); + DSCP_DEFAULT), -1, &stream); if (error) { ovs_fatal(error, "failed to connect to \"%s\"", ctx->argv[1]); } diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py index c03476c7f..2d1112ddd 100644 --- a/tests/test-ovsdb.py +++ b/tests/test-ovsdb.py @@ -604,7 +604,7 @@ def do_idl(schema_file, remote, *commands): stream = None for r in remotes: error, stream = ovs.stream.Stream.open_block( - ovs.stream.Stream.open(r)) + ovs.stream.Stream.open(r), 2000) if not error and stream: break stream = None diff --git a/tests/test-stream.c b/tests/test-stream.c index 4816de02d..4af44200e 100644 --- a/tests/test-stream.c +++ b/tests/test-stream.c @@ -37,7 +37,7 @@ main(int argc, char *argv[]) } error = stream_open_block(stream_open(argv[1], &stream, DSCP_DEFAULT), - &stream); + 10000, &stream); if (error) { VLOG_ERR("stream_open_block(%s) failure: %s", argv[1], ovs_strerror(error)); diff --git a/tests/test-stream.py b/tests/test-stream.py index 4a5117501..93d63c019 100644 --- a/tests/test-stream.py +++ b/tests/test-stream.py @@ -20,7 +20,7 @@ import ovs.stream def main(argv): remote = argv[1] err, stream = ovs.stream.Stream.open_block( - ovs.stream.Stream.open(remote)) + ovs.stream.Stream.open(remote), 10000) if err or stream is None: sys.exit(1) |