zos: track unbound handles and bind before listen

On zOS the listen call does not bind automatically if the socket
is unbound. Hence the manual binding to an arbitrary port is
required to be done manually.

PR-URL: https://github.com/libuv/libuv/pull/949
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
John Barboza 2016-07-19 09:07:28 -04:00 committed by Saúl Ibarra Corretgé
parent e37f25d776
commit f4ef897666
5 changed files with 30 additions and 1 deletions

View File

@ -132,7 +132,8 @@ enum {
UV_TCP_KEEPALIVE = 0x800, /* Turn on keep-alive. */
UV_TCP_SINGLE_ACCEPT = 0x1000, /* Only accept() when idle. */
UV_HANDLE_IPV6 = 0x10000, /* Handle is bound to a IPv6 socket. */
UV_UDP_PROCESSING = 0x20000 /* Handle is running the send callback queue. */
UV_UDP_PROCESSING = 0x20000, /* Handle is running the send callback queue. */
UV_HANDLE_BOUND = 0x40000 /* Handle is bound to an address and port */
};
/* loop flags */

View File

@ -80,6 +80,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
}
/* Success. */
handle->flags |= UV_HANDLE_BOUND;
handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */
handle->io_watcher.fd = sockfd;
return 0;

View File

@ -604,6 +604,8 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
return -EINVAL;
}
client->flags |= UV_HANDLE_BOUND;
done:
/* Process queued fds */
if (server->queued_fds != NULL) {

View File

@ -134,6 +134,7 @@ int uv__tcp_bind(uv_tcp_t* tcp,
}
tcp->delayed_error = -errno;
tcp->flags |= UV_HANDLE_BOUND;
if (addr->sa_family == AF_INET6)
tcp->flags |= UV_HANDLE_IPV6;
@ -276,10 +277,32 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
if (err)
return err;
#ifdef __MVS__
/* on zOS the listen call does not bind automatically
if the socket is unbound. Hence the manual binding to
an arbitrary port is required to be done manually
*/
if (!(tcp->flags & UV_HANDLE_BOUND)) {
struct sockaddr_storage saddr;
socklen_t slen = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
if (getsockname(tcp->io_watcher.fd, (struct sockaddr*) &saddr, &slen))
return -errno;
if (bind(tcp->io_watcher.fd, (struct sockaddr*) &saddr, slen))
return -errno;
tcp->flags |= UV_HANDLE_BOUND;
}
#endif
if (listen(tcp->io_watcher.fd, backlog))
return -errno;
tcp->connection_cb = cb;
tcp->flags |= UV_HANDLE_BOUND;
/* Start listening for connections. */
tcp->io_watcher.cb = uv__server_io;

View File

@ -335,6 +335,8 @@ int uv__udp_bind(uv_udp_t* handle,
if (addr->sa_family == AF_INET6)
handle->flags |= UV_HANDLE_IPV6;
handle->flags |= UV_HANDLE_BOUND;
return 0;
out: