I/O channels fixes 2016/01/20 v1
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJWn3AjAAoJEL6G67QVEE/fzYIP/3KS3d5CF2345IlzL9dTizyP 1OzOXGHIRpg8CJ9gixfGuyS1jUlPTAe7ov2VizmmeJoocbSZDohbXMWFrGbfPwFj KAPDBeYwEdmdkV4Tc0ZYu2hqKxOtQgKPBErzkNugIz26qkp1M82mieUcO3dIol2Y vela8AePSK4vv/STDgwAWRudb04XtLvV6I+bTD5MwPF+84QZHEXm2iAj7O6ESGah q42kigp7frnozHQQBA5yg3QLTYLD+PM9M9qFqG1S+1OtsaFUDPphRhherm7A2g54 UsuH/ctThOEIB4JrC7+XGRkJIi9ZZoMZDpwCwS9OOmAb1CS/jvyAOaxbBnmIrLyJ F2y3bJBFITvqcXUfqCFcl7a6vWfKy1Gw9EcTysGKdY5EfHp4ESoWQGCQH5PE6I9N cE7xzn4rIr+dnKDsg5qlUR9ObbHEuv7iKWe7OSpGti+EBE4fXt+AASWyZiC0bFST dvC9jjlNzQC8DIvIEjtcSwLr9hOKBbGT6S4Qsqt4ddHzliXAx2wyPshDbz879ql2 eD4tODX0QVyYxnrc3YfwqsneSFG2AZytF/wqi1FFroiYCvYBianfAxKrtx91786W ZwNqTTanO8uDEEgYwjpRMMpC1LnjrwCCEbL6XG9oxuUFzKjeAC9s+pfx7P5NKVDC JwiLP41N7GgjsExO7xjv =eFG+ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/berrange/tags/pull-io-next-2016-01-20-1' into staging I/O channels fixes 2016/01/20 v1 # gpg: Signature made Wed 20 Jan 2016 11:31:47 GMT using RSA key ID 15104FDF # gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" # gpg: aka "Daniel P. Berrange <berrange@redhat.com>" * remotes/berrange/tags/pull-io-next-2016-01-20-1: io: use memset instead of { 0 } for initializing array io: fix description of @errp parameter initialization io: some fixes to handling of /dev/null when running commands io: increment counter when killing off subcommand io: fix sign of errno value passed to error report Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3ed0b659ca
@ -51,7 +51,7 @@ struct QIOChannelCommand {
|
|||||||
* @writefd: the FD connected to the command's stdin
|
* @writefd: the FD connected to the command's stdin
|
||||||
* @readfd: the FD connected to the command's stdout
|
* @readfd: the FD connected to the command's stdout
|
||||||
* @pid: the PID of the running child command
|
* @pid: the PID of the running child command
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Create a channel for performing I/O with the
|
* Create a channel for performing I/O with the
|
||||||
* previously spawned command identified by @pid.
|
* previously spawned command identified by @pid.
|
||||||
@ -75,7 +75,7 @@ qio_channel_command_new_pid(int writefd,
|
|||||||
* qio_channel_command_new_spawn:
|
* qio_channel_command_new_spawn:
|
||||||
* @argv: the NULL terminated list of command arguments
|
* @argv: the NULL terminated list of command arguments
|
||||||
* @flags: the I/O mode, one of O_RDONLY, O_WRONLY, O_RDWR
|
* @flags: the I/O mode, one of O_RDONLY, O_WRONLY, O_RDWR
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Create a channel for performing I/O with the
|
* Create a channel for performing I/O with the
|
||||||
* command to be spawned with arguments @argv.
|
* command to be spawned with arguments @argv.
|
||||||
|
@ -67,7 +67,7 @@ qio_channel_socket_new(void);
|
|||||||
/**
|
/**
|
||||||
* qio_channel_socket_new_fd:
|
* qio_channel_socket_new_fd:
|
||||||
* @fd: the socket file descriptor
|
* @fd: the socket file descriptor
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Create a channel for performing I/O on the socket
|
* Create a channel for performing I/O on the socket
|
||||||
* connection represented by the file descriptor @fd.
|
* connection represented by the file descriptor @fd.
|
||||||
@ -83,7 +83,7 @@ qio_channel_socket_new_fd(int fd,
|
|||||||
* qio_channel_socket_connect_sync:
|
* qio_channel_socket_connect_sync:
|
||||||
* @ioc: the socket channel object
|
* @ioc: the socket channel object
|
||||||
* @addr: the address to connect to
|
* @addr: the address to connect to
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Attempt to connect to the address @addr. This method
|
* Attempt to connect to the address @addr. This method
|
||||||
* will run in the foreground so the caller will not regain
|
* will run in the foreground so the caller will not regain
|
||||||
@ -118,7 +118,7 @@ void qio_channel_socket_connect_async(QIOChannelSocket *ioc,
|
|||||||
* qio_channel_socket_listen_sync:
|
* qio_channel_socket_listen_sync:
|
||||||
* @ioc: the socket channel object
|
* @ioc: the socket channel object
|
||||||
* @addr: the address to listen to
|
* @addr: the address to listen to
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Attempt to listen to the address @addr. This method
|
* Attempt to listen to the address @addr. This method
|
||||||
* will run in the foreground so the caller will not regain
|
* will run in the foreground so the caller will not regain
|
||||||
@ -154,7 +154,7 @@ void qio_channel_socket_listen_async(QIOChannelSocket *ioc,
|
|||||||
* @ioc: the socket channel object
|
* @ioc: the socket channel object
|
||||||
* @localAddr: the address to local bind address
|
* @localAddr: the address to local bind address
|
||||||
* @remoteAddr: the address to remote peer address
|
* @remoteAddr: the address to remote peer address
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Attempt to initialize a datagram socket bound to
|
* Attempt to initialize a datagram socket bound to
|
||||||
* @localAddr and communicating with peer @remoteAddr.
|
* @localAddr and communicating with peer @remoteAddr.
|
||||||
@ -193,7 +193,7 @@ void qio_channel_socket_dgram_async(QIOChannelSocket *ioc,
|
|||||||
/**
|
/**
|
||||||
* qio_channel_socket_get_local_address:
|
* qio_channel_socket_get_local_address:
|
||||||
* @ioc: the socket channel object
|
* @ioc: the socket channel object
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Get the string representation of the local socket
|
* Get the string representation of the local socket
|
||||||
* address. A pointer to the allocated address information
|
* address. A pointer to the allocated address information
|
||||||
@ -210,7 +210,7 @@ qio_channel_socket_get_local_address(QIOChannelSocket *ioc,
|
|||||||
/**
|
/**
|
||||||
* qio_channel_socket_get_remote_address:
|
* qio_channel_socket_get_remote_address:
|
||||||
* @ioc: the socket channel object
|
* @ioc: the socket channel object
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Get the string representation of the local socket
|
* Get the string representation of the local socket
|
||||||
* address. A pointer to the allocated address information
|
* address. A pointer to the allocated address information
|
||||||
@ -228,7 +228,7 @@ qio_channel_socket_get_remote_address(QIOChannelSocket *ioc,
|
|||||||
/**
|
/**
|
||||||
* qio_channel_socket_accept:
|
* qio_channel_socket_accept:
|
||||||
* @ioc: the socket channel object
|
* @ioc: the socket channel object
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* If the socket represents a server, then this accepts
|
* If the socket represents a server, then this accepts
|
||||||
* a new client connection. The returned channel will
|
* a new client connection. The returned channel will
|
||||||
|
@ -55,7 +55,7 @@ struct QIOChannelTLS {
|
|||||||
* @master: the underlying channel object
|
* @master: the underlying channel object
|
||||||
* @creds: the credentials to use for TLS handshake
|
* @creds: the credentials to use for TLS handshake
|
||||||
* @aclname: the access control list for validating clients
|
* @aclname: the access control list for validating clients
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Create a new TLS channel that runs the server side of
|
* Create a new TLS channel that runs the server side of
|
||||||
* a TLS session. The TLS session handshake will use the
|
* a TLS session. The TLS session handshake will use the
|
||||||
@ -85,7 +85,7 @@ qio_channel_tls_new_server(QIOChannel *master,
|
|||||||
* @master: the underlying channel object
|
* @master: the underlying channel object
|
||||||
* @creds: the credentials to use for TLS handshake
|
* @creds: the credentials to use for TLS handshake
|
||||||
* @hostname: the user specified server hostname
|
* @hostname: the user specified server hostname
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Create a new TLS channel that runs the client side of
|
* Create a new TLS channel that runs the client side of
|
||||||
* a TLS session. The TLS session handshake will use the
|
* a TLS session. The TLS session handshake will use the
|
||||||
|
@ -152,7 +152,7 @@ bool qio_channel_has_feature(QIOChannel *ioc,
|
|||||||
* @niov: the length of the @iov array
|
* @niov: the length of the @iov array
|
||||||
* @fds: pointer to an array that will received file handles
|
* @fds: pointer to an array that will received file handles
|
||||||
* @nfds: pointer filled with number of elements in @fds on return
|
* @nfds: pointer filled with number of elements in @fds on return
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Read data from the IO channel, storing it in the
|
* Read data from the IO channel, storing it in the
|
||||||
* memory regions referenced by @iov. Each element
|
* memory regions referenced by @iov. Each element
|
||||||
@ -198,7 +198,7 @@ ssize_t qio_channel_readv_full(QIOChannel *ioc,
|
|||||||
* @niov: the length of the @iov array
|
* @niov: the length of the @iov array
|
||||||
* @fds: an array of file handles to send
|
* @fds: an array of file handles to send
|
||||||
* @nfds: number of file handles in @fds
|
* @nfds: number of file handles in @fds
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Write data to the IO channel, reading it from the
|
* Write data to the IO channel, reading it from the
|
||||||
* memory regions referenced by @iov. Each element
|
* memory regions referenced by @iov. Each element
|
||||||
@ -237,7 +237,7 @@ ssize_t qio_channel_writev_full(QIOChannel *ioc,
|
|||||||
* @ioc: the channel object
|
* @ioc: the channel object
|
||||||
* @iov: the array of memory regions to read data into
|
* @iov: the array of memory regions to read data into
|
||||||
* @niov: the length of the @iov array
|
* @niov: the length of the @iov array
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Behaves as qio_channel_readv_full() but does not support
|
* Behaves as qio_channel_readv_full() but does not support
|
||||||
* receiving of file handles.
|
* receiving of file handles.
|
||||||
@ -252,7 +252,7 @@ ssize_t qio_channel_readv(QIOChannel *ioc,
|
|||||||
* @ioc: the channel object
|
* @ioc: the channel object
|
||||||
* @iov: the array of memory regions to write data from
|
* @iov: the array of memory regions to write data from
|
||||||
* @niov: the length of the @iov array
|
* @niov: the length of the @iov array
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Behaves as qio_channel_writev_full() but does not support
|
* Behaves as qio_channel_writev_full() but does not support
|
||||||
* sending of file handles.
|
* sending of file handles.
|
||||||
@ -267,7 +267,7 @@ ssize_t qio_channel_writev(QIOChannel *ioc,
|
|||||||
* @ioc: the channel object
|
* @ioc: the channel object
|
||||||
* @buf: the memory region to read data into
|
* @buf: the memory region to read data into
|
||||||
* @buflen: the length of @buf
|
* @buflen: the length of @buf
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Behaves as qio_channel_readv_full() but does not support
|
* Behaves as qio_channel_readv_full() but does not support
|
||||||
* receiving of file handles, and only supports reading into
|
* receiving of file handles, and only supports reading into
|
||||||
@ -283,7 +283,7 @@ ssize_t qio_channel_read(QIOChannel *ioc,
|
|||||||
* @ioc: the channel object
|
* @ioc: the channel object
|
||||||
* @buf: the memory regions to send data from
|
* @buf: the memory regions to send data from
|
||||||
* @buflen: the length of @buf
|
* @buflen: the length of @buf
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Behaves as qio_channel_writev_full() but does not support
|
* Behaves as qio_channel_writev_full() but does not support
|
||||||
* sending of file handles, and only supports writing from a
|
* sending of file handles, and only supports writing from a
|
||||||
@ -298,7 +298,7 @@ ssize_t qio_channel_write(QIOChannel *ioc,
|
|||||||
* qio_channel_set_blocking:
|
* qio_channel_set_blocking:
|
||||||
* @ioc: the channel object
|
* @ioc: the channel object
|
||||||
* @enabled: the blocking flag state
|
* @enabled: the blocking flag state
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* If @enabled is true, then the channel is put into
|
* If @enabled is true, then the channel is put into
|
||||||
* blocking mode, otherwise it will be non-blocking.
|
* blocking mode, otherwise it will be non-blocking.
|
||||||
@ -314,7 +314,7 @@ int qio_channel_set_blocking(QIOChannel *ioc,
|
|||||||
/**
|
/**
|
||||||
* qio_channel_close:
|
* qio_channel_close:
|
||||||
* @ioc: the channel object
|
* @ioc: the channel object
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Close the channel, flushing any pending I/O
|
* Close the channel, flushing any pending I/O
|
||||||
*
|
*
|
||||||
@ -327,7 +327,7 @@ int qio_channel_close(QIOChannel *ioc,
|
|||||||
* qio_channel_shutdown:
|
* qio_channel_shutdown:
|
||||||
* @ioc: the channel object
|
* @ioc: the channel object
|
||||||
* @how: the direction to shutdown
|
* @how: the direction to shutdown
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Shutdowns transmission and/or receiving of data
|
* Shutdowns transmission and/or receiving of data
|
||||||
* without closing the underlying transport.
|
* without closing the underlying transport.
|
||||||
@ -403,7 +403,7 @@ void qio_channel_set_cork(QIOChannel *ioc,
|
|||||||
* @ioc: the channel object
|
* @ioc: the channel object
|
||||||
* @offset: the position to seek to, relative to @whence
|
* @offset: the position to seek to, relative to @whence
|
||||||
* @whence: one of the (POSIX) SEEK_* constants listed below
|
* @whence: one of the (POSIX) SEEK_* constants listed below
|
||||||
* @errp: pointer to an uninitialized error object
|
* @errp: pointer to a NULL-initialized error object
|
||||||
*
|
*
|
||||||
* Moves the current I/O position within the channel
|
* Moves the current I/O position within the channel
|
||||||
* @ioc, to be @offset. The value of @offset is
|
* @ioc, to be @offset. The value of @offset is
|
||||||
|
@ -66,7 +66,7 @@ qio_channel_command_new_spawn(const char *const argv[],
|
|||||||
|
|
||||||
if (stdinnull || stdoutnull) {
|
if (stdinnull || stdoutnull) {
|
||||||
devnull = open("/dev/null", O_RDWR);
|
devnull = open("/dev/null", O_RDWR);
|
||||||
if (!devnull) {
|
if (devnull < 0) {
|
||||||
error_setg_errno(errp, errno,
|
error_setg_errno(errp, errno,
|
||||||
"Unable to open /dev/null");
|
"Unable to open /dev/null");
|
||||||
goto error;
|
goto error;
|
||||||
@ -98,6 +98,9 @@ qio_channel_command_new_spawn(const char *const argv[],
|
|||||||
close(stdoutfd[0]);
|
close(stdoutfd[0]);
|
||||||
close(stdoutfd[1]);
|
close(stdoutfd[1]);
|
||||||
}
|
}
|
||||||
|
if (devnull != -1) {
|
||||||
|
close(devnull);
|
||||||
|
}
|
||||||
|
|
||||||
execv(argv[0], (char * const *)argv);
|
execv(argv[0], (char * const *)argv);
|
||||||
_exit(1);
|
_exit(1);
|
||||||
@ -117,6 +120,9 @@ qio_channel_command_new_spawn(const char *const argv[],
|
|||||||
return ioc;
|
return ioc;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
if (devnull != -1) {
|
||||||
|
close(devnull);
|
||||||
|
}
|
||||||
if (stdinfd[0] != -1) {
|
if (stdinfd[0] != -1) {
|
||||||
close(stdinfd[0]);
|
close(stdinfd[0]);
|
||||||
}
|
}
|
||||||
@ -179,6 +185,7 @@ static int qio_channel_command_abort(QIOChannelCommand *ioc,
|
|||||||
(unsigned long long)ioc->pid);
|
(unsigned long long)ioc->pid);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
step++;
|
||||||
usleep(10 * 1000);
|
usleep(10 * 1000);
|
||||||
goto rewait;
|
goto rewait;
|
||||||
}
|
}
|
||||||
@ -201,12 +208,12 @@ static void qio_channel_command_finalize(Object *obj)
|
|||||||
QIOChannelCommand *ioc = QIO_CHANNEL_COMMAND(obj);
|
QIOChannelCommand *ioc = QIO_CHANNEL_COMMAND(obj);
|
||||||
if (ioc->readfd != -1) {
|
if (ioc->readfd != -1) {
|
||||||
close(ioc->readfd);
|
close(ioc->readfd);
|
||||||
ioc->readfd = -1;
|
|
||||||
}
|
}
|
||||||
if (ioc->writefd != -1) {
|
if (ioc->writefd != -1 &&
|
||||||
|
ioc->writefd != ioc->readfd) {
|
||||||
close(ioc->writefd);
|
close(ioc->writefd);
|
||||||
ioc->writefd = -1;
|
|
||||||
}
|
}
|
||||||
|
ioc->writefd = ioc->readfd = -1;
|
||||||
if (ioc->pid > 0) {
|
if (ioc->pid > 0) {
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
qio_channel_command_abort(ioc, NULL);
|
qio_channel_command_abort(ioc, NULL);
|
||||||
@ -298,12 +305,16 @@ static int qio_channel_command_close(QIOChannel *ioc,
|
|||||||
/* We close FDs before killing, because that
|
/* We close FDs before killing, because that
|
||||||
* gives a better chance of clean shutdown
|
* gives a better chance of clean shutdown
|
||||||
*/
|
*/
|
||||||
if (close(cioc->writefd) < 0) {
|
if (cioc->readfd != -1 &&
|
||||||
|
close(cioc->readfd) < 0) {
|
||||||
rv = -1;
|
rv = -1;
|
||||||
}
|
}
|
||||||
if (close(cioc->readfd) < 0) {
|
if (cioc->writefd != -1 &&
|
||||||
|
cioc->writefd != cioc->readfd &&
|
||||||
|
close(cioc->writefd) < 0) {
|
||||||
rv = -1;
|
rv = -1;
|
||||||
}
|
}
|
||||||
|
cioc->writefd = cioc->readfd = -1;
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if (qio_channel_command_abort(cioc, errp) < 0) {
|
if (qio_channel_command_abort(cioc, errp) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -449,6 +449,8 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
|
|||||||
char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)];
|
char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)];
|
||||||
int sflags = 0;
|
int sflags = 0;
|
||||||
|
|
||||||
|
memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS));
|
||||||
|
|
||||||
#ifdef MSG_CMSG_CLOEXEC
|
#ifdef MSG_CMSG_CLOEXEC
|
||||||
sflags |= MSG_CMSG_CLOEXEC;
|
sflags |= MSG_CMSG_CLOEXEC;
|
||||||
#endif
|
#endif
|
||||||
@ -493,16 +495,18 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc,
|
|||||||
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
|
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
struct msghdr msg = { NULL, };
|
struct msghdr msg = { NULL, };
|
||||||
char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)] = { 0 };
|
char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)];
|
||||||
size_t fdsize = sizeof(int) * nfds;
|
size_t fdsize = sizeof(int) * nfds;
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
|
|
||||||
|
memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS));
|
||||||
|
|
||||||
msg.msg_iov = (struct iovec *)iov;
|
msg.msg_iov = (struct iovec *)iov;
|
||||||
msg.msg_iovlen = niov;
|
msg.msg_iovlen = niov;
|
||||||
|
|
||||||
if (nfds) {
|
if (nfds) {
|
||||||
if (nfds > SOCKET_MAX_FDS) {
|
if (nfds > SOCKET_MAX_FDS) {
|
||||||
error_setg_errno(errp, -EINVAL,
|
error_setg_errno(errp, EINVAL,
|
||||||
"Only %d FDs can be sent, got %zu",
|
"Only %d FDs can be sent, got %zu",
|
||||||
SOCKET_MAX_FDS, nfds);
|
SOCKET_MAX_FDS, nfds);
|
||||||
return -1;
|
return -1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user