summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixSock.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2020-12-06 18:24:00 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2020-12-06 18:24:00 (GMT)
commit0f93742804d047a8de0fe3acda7b019daae7b273 (patch)
tree18bed9fa65dbe84ebb028ca81c52ae123e9b3867 /unix/tclUnixSock.c
parent7dd7fe1b6c5348772912a64134334358a39f8211 (diff)
parentfcee72d2c7daddae9dd63e4eb14746b7bd319aa9 (diff)
downloadtcl-0f93742804d047a8de0fe3acda7b019daae7b273.zip
tcl-0f93742804d047a8de0fe3acda7b019daae7b273.tar.gz
tcl-0f93742804d047a8de0fe3acda7b019daae7b273.tar.bz2
merge core-8-branch
Diffstat (limited to 'unix/tclUnixSock.c')
-rw-r--r--unix/tclUnixSock.c172
1 files changed, 108 insertions, 64 deletions
diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c
index 57735da..8c9386c 100644
--- a/unix/tclUnixSock.c
+++ b/unix/tclUnixSock.c
@@ -66,7 +66,7 @@ struct TcpState {
Tcl_TcpAcceptProc *acceptProc;
/* Proc to call on accept. */
- ClientData acceptProcData; /* The data for the accept proc. */
+ void *acceptProcData; /* The data for the accept proc. */
/*
* Only needed for client sockets
@@ -129,25 +129,27 @@ struct TcpState {
* Static routines for this file:
*/
+static void TcpAsyncCallback(void *clientData, int mask);
static int TcpConnect(Tcl_Interp *interp, TcpState *state);
-static void TcpAccept(ClientData data, int mask);
-static int TcpBlockModeProc(ClientData data, int mode);
-static int TcpCloseProc(ClientData instanceData,
+static void TcpAccept(void *data, int mask);
+static int TcpBlockModeProc(void *data, int mode);
+static int TcpCloseProc(void *instanceData,
Tcl_Interp *interp);
-static int TcpClose2Proc(ClientData instanceData,
+static int TcpClose2Proc(void *instanceData,
Tcl_Interp *interp, int flags);
-static int TcpGetHandleProc(ClientData instanceData,
- int direction, ClientData *handlePtr);
-static int TcpGetOptionProc(ClientData instanceData,
+static int TcpGetHandleProc(void *instanceData,
+ int direction, void **handlePtr);
+static int TcpGetOptionProc(void *instanceData,
Tcl_Interp *interp, const char *optionName,
Tcl_DString *dsPtr);
-static int TcpInputProc(ClientData instanceData, char *buf,
+static int TcpInputProc(void *instanceData, char *buf,
int toRead, int *errorCode);
-static int TcpOutputProc(ClientData instanceData,
+static int TcpOutputProc(void *instanceData,
const char *buf, int toWrite, int *errorCode);
-static void TcpWatchProc(ClientData instanceData, int mask);
+static void TcpThreadActionProc(void *instanceData, int action);
+static void TcpWatchProc(void *instanceData, int mask);
static int WaitForConnect(TcpState *statePtr, int *errorCodePtr);
-static void WrapNotify(ClientData clientData, int mask);
+static void WrapNotify(void *clientData, int mask);
/*
* This structure describes the channel type structure for TCP socket
@@ -157,7 +159,11 @@ static void WrapNotify(ClientData clientData, int mask);
static const Tcl_ChannelType tcpChannelType = {
"tcp", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
+#ifndef TCL_NO_DEPRECATED
TcpCloseProc, /* Close proc. */
+#else
+ TCL_CLOSE2PROC, /* Close proc. */
+#endif
TcpInputProc, /* Input proc. */
TcpOutputProc, /* Output proc. */
NULL, /* Seek proc. */
@@ -170,7 +176,7 @@ static const Tcl_ChannelType tcpChannelType = {
NULL, /* flush proc. */
NULL, /* handler proc. */
NULL, /* wide seek proc. */
- NULL, /* thread action proc. */
+ TcpThreadActionProc, /* thread action proc. */
NULL /* truncate proc. */
};
@@ -227,7 +233,7 @@ InitializeHostName(
struct hostent *hp;
memset(&u, (int) 0, sizeof(struct utsname));
- if (uname(&u) > -1) { /* INTL: Native. */
+ if (uname(&u) >= 0) { /* INTL: Native. */
hp = TclpGetHostByName(u.nodename); /* INTL: Native. */
if (hp == NULL) {
/*
@@ -239,7 +245,7 @@ InitializeHostName(
char *dot = strchr(u.nodename, '.');
if (dot != NULL) {
- char *node = ckalloc(dot - u.nodename + 1);
+ char *node = (char *)ckalloc(dot - u.nodename + 1);
memcpy(node, u.nodename, dot - u.nodename);
node[dot - u.nodename] = '\0';
@@ -275,7 +281,7 @@ InitializeHostName(
char buffer[256];
# endif
- if (gethostname(buffer, sizeof(buffer)) > -1) { /* INTL: Native. */
+ if (gethostname(buffer, sizeof(buffer)) >= 0) { /* INTL: Native. */
native = buffer;
}
#endif /* NO_UNAME */
@@ -283,11 +289,11 @@ InitializeHostName(
*encodingPtr = Tcl_GetEncoding(NULL, NULL);
if (native) {
*lengthPtr = strlen(native);
- *valuePtr = ckalloc(*lengthPtr + 1);
+ *valuePtr = (char *)ckalloc(*lengthPtr + 1);
memcpy(*valuePtr, native, *lengthPtr + 1);
} else {
*lengthPtr = 0;
- *valuePtr = ckalloc(1);
+ *valuePtr = (char *)ckalloc(1);
*valuePtr[0] = '\0';
}
}
@@ -334,7 +340,7 @@ Tcl_GetHostName(void)
int
TclpHasSockets(
- Tcl_Interp *interp) /* Not used. */
+ TCL_UNUSED(Tcl_Interp *))
{
return TCL_OK;
}
@@ -378,15 +384,14 @@ TclpFinalizeSockets(void)
* ----------------------------------------------------------------------
*/
- /* ARGSUSED */
static int
TcpBlockModeProc(
- ClientData instanceData, /* Socket state. */
+ void *instanceData, /* Socket state. */
int mode) /* The mode to set. Can be one of
* TCL_MODE_BLOCKING or
* TCL_MODE_NONBLOCKING. */
{
- TcpState *statePtr = instanceData;
+ TcpState *statePtr = (TcpState *)instanceData;
if (mode == TCL_MODE_BLOCKING) {
CLEAR_BITS(statePtr->flags, TCP_NONBLOCKING);
@@ -524,16 +529,15 @@ WaitForConnect(
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
static int
TcpInputProc(
- ClientData instanceData, /* Socket state. */
+ void *instanceData, /* Socket state. */
char *buf, /* Where to store data read. */
int bufSize, /* How much space is available in the
* buffer? */
int *errorCodePtr) /* Where to store error code. */
{
- TcpState *statePtr = instanceData;
+ TcpState *statePtr = (TcpState *)instanceData;
int bytesRead;
*errorCodePtr = 0;
@@ -541,7 +545,7 @@ TcpInputProc(
return -1;
}
bytesRead = recv(statePtr->fds.fd, buf, (size_t) bufSize, 0);
- if (bytesRead > -1) {
+ if (bytesRead >= 0) {
return bytesRead;
}
if (errno == ECONNRESET) {
@@ -578,12 +582,12 @@ TcpInputProc(
static int
TcpOutputProc(
- ClientData instanceData, /* Socket state. */
+ void *instanceData, /* Socket state. */
const char *buf, /* The data buffer. */
int toWrite, /* How many bytes to write? */
int *errorCodePtr) /* Where to store error code. */
{
- TcpState *statePtr = instanceData;
+ TcpState *statePtr = (TcpState *)instanceData;
int written;
*errorCodePtr = 0;
@@ -592,7 +596,7 @@ TcpOutputProc(
}
written = send(statePtr->fds.fd, buf, (size_t) toWrite, 0);
- if (written > -1) {
+ if (written >= 0) {
return written;
}
*errorCodePtr = errno;
@@ -617,13 +621,12 @@ TcpOutputProc(
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
static int
TcpCloseProc(
- ClientData instanceData, /* The socket to close. */
- Tcl_Interp *interp) /* For error reporting - unused. */
+ void *instanceData, /* The socket to close. */
+ TCL_UNUSED(Tcl_Interp *))
{
- TcpState *statePtr = instanceData;
+ TcpState *statePtr = (TcpState *)instanceData;
int errorCode = 0;
TcpFdList *fds;
@@ -681,11 +684,11 @@ TcpCloseProc(
static int
TcpClose2Proc(
- ClientData instanceData, /* The socket to close. */
- Tcl_Interp *interp, /* For error reporting. */
+ void *instanceData, /* The socket to close. */
+ TCL_UNUSED(Tcl_Interp *),
int flags) /* Flags that indicate which side to close. */
{
- TcpState *statePtr = instanceData;
+ TcpState *statePtr = (TcpState *)instanceData;
int readError = 0;
int writeError = 0;
@@ -693,7 +696,7 @@ TcpClose2Proc(
* Shutdown the OS socket handle.
*/
if ((flags & (TCL_CLOSE_READ|TCL_CLOSE_WRITE)) == 0) {
- return TcpCloseProc(instanceData, interp);
+ return TcpCloseProc(instanceData, NULL);
}
if ((flags & TCL_CLOSE_READ) && (shutdown(statePtr->fds.fd, SHUT_RD) < 0)) {
readError = errno;
@@ -832,7 +835,7 @@ TcpHostPortList(
static int
TcpGetOptionProc(
- ClientData instanceData, /* Socket state. */
+ void *instanceData, /* Socket state. */
Tcl_Interp *interp, /* For error reporting - can be NULL. */
const char *optionName, /* Name of the option to retrieve the value
* for, or NULL to get all options and their
@@ -840,7 +843,7 @@ TcpGetOptionProc(
Tcl_DString *dsPtr) /* Where to store the computed value;
* initialized by caller. */
{
- TcpState *statePtr = instanceData;
+ TcpState *statePtr = (TcpState *)instanceData;
size_t len = 0;
WaitForConnect(statePtr, NULL);
@@ -982,6 +985,51 @@ TcpGetOptionProc(
/*
* ----------------------------------------------------------------------
*
+ * TcpThreadActionProc --
+ *
+ * Handles detach/attach for asynchronously connecting socket.
+ *
+ * Reassigning the file handler associated with thread-related channel
+ * notification, responsible for callbacks (signaling that asynchronous
+ * connection attempt has succeeded or failed).
+ *
+ * Results:
+ * None.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static void
+TcpThreadActionProc(
+ void *instanceData,
+ int action)
+{
+ TcpState *statePtr = (TcpState *)instanceData;
+
+ if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
+ /*
+ * Async-connecting socket must get reassigned handler if it have been
+ * transferred to another thread. Remove the handler if the socket is
+ * not managed by this thread anymore and create new handler (TSD related)
+ * so the callback will run in the correct thread, bug [f583715154].
+ */
+ switch (action) {
+ case TCL_CHANNEL_THREAD_REMOVE:
+ CLEAR_BITS(statePtr->flags, TCP_ASYNC_PENDING);
+ Tcl_DeleteFileHandler(statePtr->fds.fd);
+ break;
+ case TCL_CHANNEL_THREAD_INSERT:
+ Tcl_CreateFileHandler(statePtr->fds.fd,
+ TCL_WRITABLE | TCL_EXCEPTION, TcpAsyncCallback, statePtr);
+ SET_BITS(statePtr->flags, TCP_ASYNC_PENDING);
+ break;
+ }
+ }
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
* TcpWatchProc --
*
* Initialize the notifier to watch the fd from this channel.
@@ -998,7 +1046,7 @@ TcpGetOptionProc(
static void
WrapNotify(
- ClientData clientData,
+ void *clientData,
int mask)
{
TcpState *statePtr = (TcpState *) clientData;
@@ -1027,12 +1075,12 @@ WrapNotify(
static void
TcpWatchProc(
- ClientData instanceData, /* The socket state. */
+ void *instanceData, /* The socket state. */
int mask) /* Events of interest; an OR-ed combination of
* TCL_READABLE, TCL_WRITABLE and
* TCL_EXCEPTION. */
{
- TcpState *statePtr = instanceData;
+ TcpState *statePtr = (TcpState *)instanceData;
if (statePtr->acceptProc != NULL) {
/*
@@ -1098,14 +1146,13 @@ TcpWatchProc(
* ----------------------------------------------------------------------
*/
- /* ARGSUSED */
static int
TcpGetHandleProc(
- ClientData instanceData, /* The socket state. */
- int direction, /* Not used. */
- ClientData *handlePtr) /* Where to store the handle. */
+ void *instanceData, /* The socket state. */
+ TCL_UNUSED(int) /*direction*/,
+ void **handlePtr) /* Where to store the handle. */
{
- TcpState *statePtr = instanceData;
+ TcpState *statePtr = (TcpState *)instanceData;
*handlePtr = INT2PTR(statePtr->fds.fd);
return TCL_OK;
@@ -1125,12 +1172,10 @@ TcpGetHandleProc(
static void
TcpAsyncCallback(
- ClientData clientData, /* The socket state. */
- int mask) /* Events of interest; an OR-ed combination of
- * TCL_READABLE, TCL_WRITABLE and
- * TCL_EXCEPTION. */
+ void *clientData, /* The socket state. */
+ TCL_UNUSED(int) /*mask*/)
{
- TcpConnect(NULL, clientData);
+ TcpConnect(NULL, (TcpState *)clientData);
}
/*
@@ -1172,6 +1217,7 @@ TcpConnect(
int async_callback = GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING);
int ret = -1, error = EHOSTUNREACH;
int async = GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
+ static const int reuseaddr = 1;
if (async_callback) {
goto reenter;
@@ -1182,7 +1228,6 @@ TcpConnect(
for (statePtr->myaddr = statePtr->myaddrlist;
statePtr->myaddr != NULL;
statePtr->myaddr = statePtr->myaddr->ai_next) {
- int reuseaddr = 1;
/*
* No need to try combinations of local and remote addresses of
@@ -1389,7 +1434,7 @@ Tcl_OpenTcpClient(
* Allocate a new TcpState for this socket.
*/
- statePtr = ckalloc(sizeof(TcpState));
+ statePtr = (TcpState *)ckalloc(sizeof(TcpState));
memset(statePtr, 0, sizeof(TcpState));
statePtr->flags = async ? TCP_ASYNC_CONNECT : 0;
statePtr->cachedBlocking = TCL_MODE_BLOCKING;
@@ -1436,7 +1481,7 @@ Tcl_OpenTcpClient(
Tcl_Channel
Tcl_MakeTcpClientChannel(
- ClientData sock) /* The socket to wrap up into a channel. */
+ void *sock) /* The socket to wrap up into a channel. */
{
return (Tcl_Channel) TclpMakeTcpClientChannelMode(sock,
TCL_READABLE | TCL_WRITABLE);
@@ -1468,7 +1513,7 @@ TclpMakeTcpClientChannelMode(
TcpState *statePtr;
char channelName[SOCK_CHAN_LENGTH];
- statePtr = ckalloc(sizeof(TcpState));
+ statePtr = (TcpState *)ckalloc(sizeof(TcpState));
memset(statePtr, 0, sizeof(TcpState));
statePtr->fds.fd = PTR2INT(sock);
statePtr->flags = 0;
@@ -1511,7 +1556,7 @@ Tcl_OpenTcpServerEx(
Tcl_TcpAcceptProc *acceptProc,
/* Callback for accepting connections from new
* clients. */
- ClientData acceptProcData) /* Data for the callback. */
+ void *acceptProcData) /* Data for the callback. */
{
int status = 0, sock = -1, optvalue, port, chosenport;
struct addrinfo *addrlist = NULL, *addrPtr; /* socket address */
@@ -1691,14 +1736,14 @@ Tcl_OpenTcpServerEx(
* Allocate a new TcpState for this socket.
*/
- statePtr = ckalloc(sizeof(TcpState));
+ statePtr = (TcpState *)ckalloc(sizeof(TcpState));
memset(statePtr, 0, sizeof(TcpState));
statePtr->acceptProc = acceptProc;
statePtr->acceptProcData = acceptProcData;
sprintf(channelName, SOCK_TEMPLATE, (long) statePtr);
newfds = &statePtr->fds;
} else {
- newfds = ckalloc(sizeof(TcpFdList));
+ newfds = (TcpFdList *)ckalloc(sizeof(TcpFdList));
memset(newfds, (int) 0, sizeof(TcpFdList));
fds->next = newfds;
}
@@ -1756,13 +1801,12 @@ Tcl_OpenTcpServerEx(
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
static void
TcpAccept(
- ClientData data, /* Callback token. */
- int mask) /* Not used. */
+ void *data, /* Callback token. */
+ TCL_UNUSED(int) /*mask*/)
{
- TcpFdList *fds = data; /* Client data of server socket. */
+ TcpFdList *fds = (TcpFdList *)data; /* Client data of server socket. */
int newsock; /* The new client socket */
TcpState *newSockState; /* State for new socket. */
address addr; /* The remote address */
@@ -1783,7 +1827,7 @@ TcpAccept(
(void) fcntl(newsock, F_SETFD, FD_CLOEXEC);
- newSockState = ckalloc(sizeof(TcpState));
+ newSockState = (TcpState *)ckalloc(sizeof(TcpState));
memset(newSockState, 0, sizeof(TcpState));
newSockState->flags = 0;
newSockState->fds.fd = newsock;