Skip to content

Commit d807036

Browse files
committed
patch 7.4.1324
Problem: Channels with pipes don't work on MS-Windows. Solution: Add pipe I/O support. (Yasuhiro Matsumoto)
1 parent a971df8 commit d807036

File tree

7 files changed

+161
-66
lines changed

7 files changed

+161
-66
lines changed

src/channel.c

+115-56
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,9 @@
3232
# undef EINTR
3333
# endif
3434
# define EINTR WSAEINTR
35-
# define sock_write(sd, buf, len) send(sd, buf, len, 0)
36-
# define sock_read(sd, buf, len) recv(sd, buf, len, 0)
37-
# define sock_close(sd) closesocket(sd)
38-
# define sleep(t) Sleep(t*1000) /* WinAPI Sleep() accepts milliseconds */
35+
# define sock_write(sd, buf, len) send((SOCKET)sd, buf, len, 0)
36+
# define sock_read(sd, buf, len) recv((SOCKET)sd, buf, len, 0)
37+
# define sock_close(sd) closesocket((SOCKET)sd)
3938
#else
4039
# include <netdb.h>
4140
# include <netinet/in.h>
@@ -48,12 +47,46 @@
4847
# define sock_write(sd, buf, len) write(sd, buf, len)
4948
# define sock_read(sd, buf, len) read(sd, buf, len)
5049
# define sock_close(sd) close(sd)
50+
# define fd_read(fd, buf, len, timeout) read(fd, buf, len)
51+
# define fd_write(sd, buf, len) write(sd, buf, len)
52+
# define fd_close(sd) close(sd)
5153
#endif
5254

5355
#ifdef FEAT_GUI_W32
5456
extern HWND s_hwnd; /* Gvim's Window handle */
5557
#endif
5658

59+
#ifdef WIN32
60+
static int
61+
fd_read(sock_T fd, char_u *buf, size_t len, int timeout)
62+
{
63+
HANDLE h = (HANDLE)fd;
64+
DWORD nread;
65+
66+
if (!ReadFile(h, buf, (DWORD)len, &nread, NULL))
67+
return -1;
68+
return (int)nread;
69+
}
70+
71+
static int
72+
fd_write(sock_T fd, char_u *buf, size_t len)
73+
{
74+
HANDLE h = (HANDLE)fd;
75+
DWORD nwrite;
76+
77+
if (!WriteFile(h, buf, (DWORD)len, &nwrite, NULL))
78+
return -1;
79+
return (int)nwrite;
80+
}
81+
82+
static void
83+
fd_close(sock_T fd)
84+
{
85+
HANDLE h = (HANDLE)fd;
86+
87+
CloseHandle(h);
88+
}
89+
#endif
5790

5891
/* Log file opened with ch_logfile(). */
5992
static FILE *log_fd = NULL;
@@ -228,7 +261,7 @@ add_channel(void)
228261
which = CHAN_SOCK;
229262
#endif
230263
{
231-
channel->ch_pfd[which].ch_fd = (sock_T)-1;
264+
channel->ch_pfd[which].ch_fd = CHAN_FD_INVALID;
232265
#ifdef FEAT_GUI_X11
233266
channel->ch_pfd[which].ch_inputHandler = (XtInputId)NULL;
234267
#endif
@@ -363,12 +396,12 @@ channel_gui_register(channel_T *channel)
363396
if (!CH_HAS_GUI)
364397
return;
365398

366-
if (channel->CH_SOCK >= 0)
399+
if (channel->CH_SOCK != CHAN_FD_INVALID)
367400
channel_gui_register_one(channel, CHAN_SOCK);
368401
# ifdef CHANNEL_PIPES
369-
if (channel->CH_OUT >= 0)
402+
if (channel->CH_OUT != CHAN_FD_INVALID)
370403
channel_gui_register_one(channel, CHAN_OUT);
371-
if (channel->CH_ERR >= 0)
404+
if (channel->CH_ERR != CHAN_FD_INVALID)
372405
channel_gui_register_one(channel, CHAN_ERR);
373406
# endif
374407
}
@@ -457,7 +490,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
457490
return NULL;
458491
}
459492

460-
if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
493+
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
461494
{
462495
ch_error(NULL, "in socket() in channel_open().\n");
463496
PERROR("E898: socket() in channel_open()");
@@ -564,7 +597,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
564597
if (errno == ECONNREFUSED && close_cb != NULL)
565598
{
566599
sock_close(sd);
567-
if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
600+
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
568601
{
569602
SOCK_ERRNO;
570603
ch_log(NULL, "socket() retry in channel_open()\n");
@@ -609,7 +642,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
609642
}
610643
}
611644

612-
channel->CH_SOCK = sd;
645+
channel->CH_SOCK = (sock_T)sd;
613646
channel->ch_close_cb = close_cb;
614647

615648
#ifdef FEAT_GUI
@@ -621,7 +654,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
621654

622655
#if defined(CHANNEL_PIPES) || defined(PROTO)
623656
void
624-
channel_set_pipes(channel_T *channel, int in, int out, int err)
657+
channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err)
625658
{
626659
channel->CH_IN = in;
627660
channel->CH_OUT = out;
@@ -1144,9 +1177,9 @@ may_invoke_callback(channel_T *channel)
11441177
int
11451178
channel_can_write_to(channel_T *channel)
11461179
{
1147-
return channel != NULL && (channel->CH_SOCK >= 0
1180+
return channel != NULL && (channel->CH_SOCK != CHAN_FD_INVALID
11481181
#ifdef CHANNEL_PIPES
1149-
|| channel->CH_IN >= 0
1182+
|| channel->CH_IN != CHAN_FD_INVALID
11501183
#endif
11511184
);
11521185
}
@@ -1158,11 +1191,11 @@ channel_can_write_to(channel_T *channel)
11581191
int
11591192
channel_is_open(channel_T *channel)
11601193
{
1161-
return channel != NULL && (channel->CH_SOCK >= 0
1194+
return channel != NULL && (channel->CH_SOCK != CHAN_FD_INVALID
11621195
#ifdef CHANNEL_PIPES
1163-
|| channel->CH_IN >= 0
1164-
|| channel->CH_OUT >= 0
1165-
|| channel->CH_ERR >= 0
1196+
|| channel->CH_IN != CHAN_FD_INVALID
1197+
|| channel->CH_OUT != CHAN_FD_INVALID
1198+
|| channel->CH_ERR != CHAN_FD_INVALID
11661199
#endif
11671200
);
11681201
}
@@ -1193,26 +1226,26 @@ channel_close(channel_T *channel)
11931226
channel_gui_unregister(channel);
11941227
#endif
11951228

1196-
if (channel->CH_SOCK >= 0)
1229+
if (channel->CH_SOCK != CHAN_FD_INVALID)
11971230
{
11981231
sock_close(channel->CH_SOCK);
1199-
channel->CH_SOCK = -1;
1232+
channel->CH_SOCK = CHAN_FD_INVALID;
12001233
}
12011234
#if defined(CHANNEL_PIPES)
1202-
if (channel->CH_IN >= 0)
1235+
if (channel->CH_IN != CHAN_FD_INVALID)
12031236
{
1204-
close(channel->CH_IN);
1205-
channel->CH_IN = -1;
1237+
fd_close(channel->CH_IN);
1238+
channel->CH_IN = CHAN_FD_INVALID;
12061239
}
1207-
if (channel->CH_OUT >= 0)
1240+
if (channel->CH_OUT != CHAN_FD_INVALID)
12081241
{
1209-
close(channel->CH_OUT);
1210-
channel->CH_OUT = -1;
1242+
fd_close(channel->CH_OUT);
1243+
channel->CH_OUT = CHAN_FD_INVALID;
12111244
}
1212-
if (channel->CH_ERR >= 0)
1245+
if (channel->CH_ERR != CHAN_FD_INVALID)
12131246
{
1214-
close(channel->CH_ERR);
1215-
channel->CH_ERR = -1;
1247+
fd_close(channel->CH_ERR);
1248+
channel->CH_ERR = CHAN_FD_INVALID;
12161249
}
12171250
#endif
12181251

@@ -1325,7 +1358,7 @@ channel_free_all(void)
13251358
* Always returns OK for FEAT_GUI_W32.
13261359
*/
13271360
static int
1328-
channel_wait(channel_T *channel, int fd, int timeout)
1361+
channel_wait(channel_T *channel, sock_T fd, int timeout)
13291362
{
13301363
#if defined(HAVE_SELECT) && !defined(FEAT_GUI_W32)
13311364
struct timeval tval;
@@ -1334,13 +1367,38 @@ channel_wait(channel_T *channel, int fd, int timeout)
13341367

13351368
if (timeout > 0)
13361369
ch_logn(channel, "Waiting for %d msec\n", timeout);
1370+
1371+
1372+
# ifdef WIN32
1373+
if (channel->CH_SOCK == CHAN_FD_INVALID)
1374+
{
1375+
DWORD nread;
1376+
int diff;
1377+
DWORD deadline = GetTickCount() + timeout;
1378+
1379+
/* reading from a pipe, not a socket */
1380+
while (TRUE)
1381+
{
1382+
if (PeekNamedPipe(fd, NULL, 0, NULL, &nread, NULL) && nread > 0)
1383+
return OK;
1384+
diff = deadline - GetTickCount();
1385+
if (diff < 0)
1386+
break;
1387+
/* Wait for 5 msec.
1388+
* TODO: increase the sleep time when looping more often */
1389+
Sleep(5);
1390+
}
1391+
return FAIL;
1392+
}
1393+
#endif
1394+
13371395
FD_ZERO(&rfds);
1338-
FD_SET(fd, &rfds);
1396+
FD_SET((int)fd, &rfds);
13391397
tval.tv_sec = timeout / 1000;
13401398
tval.tv_usec = (timeout % 1000) * 1000;
13411399
for (;;)
13421400
{
1343-
ret = select(fd + 1, &rfds, NULL, NULL, &tval);
1401+
ret = select((int)fd + 1, &rfds, NULL, NULL, &tval);
13441402
# ifdef EINTR
13451403
if (ret == -1 && errno == EINTR)
13461404
continue;
@@ -1385,17 +1443,17 @@ channel_get_id(void)
13851443
* Get the file descriptor to read from, either the socket or stdout.
13861444
* TODO: should have a way to read stderr.
13871445
*/
1388-
static int
1446+
static sock_T
13891447
get_read_fd(channel_T *channel)
13901448
{
1391-
if (channel->CH_SOCK >= 0)
1449+
if (channel->CH_SOCK != CHAN_FD_INVALID)
13921450
return channel->CH_SOCK;
13931451
#if defined(CHANNEL_PIPES)
1394-
if (channel->CH_OUT >= 0)
1452+
if (channel->CH_OUT != CHAN_FD_INVALID)
13951453
return channel->CH_OUT;
13961454
#endif
13971455
ch_error(channel, "channel_read() called while socket is closed\n");
1398-
return -1;
1456+
return CHAN_FD_INVALID;
13991457
}
14001458

14011459
/*
@@ -1410,14 +1468,14 @@ channel_read(channel_T *channel, int which, char *func)
14101468
static char_u *buf = NULL;
14111469
int len = 0;
14121470
int readlen = 0;
1413-
int fd;
1471+
sock_T fd;
14141472
int use_socket = FALSE;
14151473

14161474
if (which < 0)
14171475
fd = get_read_fd(channel);
14181476
else
14191477
fd = channel->ch_pfd[which].ch_fd;
1420-
if (fd < 0)
1478+
if (fd == CHAN_FD_INVALID)
14211479
return;
14221480
use_socket = fd == channel->CH_SOCK;
14231481

@@ -1439,7 +1497,7 @@ channel_read(channel_T *channel, int which, char *func)
14391497
if (use_socket)
14401498
len = sock_read(fd, buf, MAXMSGSIZE);
14411499
else
1442-
len = read(fd, buf, MAXMSGSIZE);
1500+
len = fd_read(fd, buf, MAXMSGSIZE, channel->ch_timeout);
14431501
if (len <= 0)
14441502
break; /* error or nothing more to read */
14451503

@@ -1509,12 +1567,13 @@ channel_read_block(channel_T *channel)
15091567
ch_log(channel, "Reading raw\n");
15101568
if (channel_peek(channel) == NULL)
15111569
{
1512-
int fd = get_read_fd(channel);
1570+
sock_T fd = get_read_fd(channel);
15131571

15141572
/* TODO: read both out and err if they are different */
15151573
ch_log(channel, "No readahead\n");
15161574
/* Wait for up to the channel timeout. */
1517-
if (fd < 0 || channel_wait(channel, fd, channel->ch_timeout) == FAIL)
1575+
if (fd == CHAN_FD_INVALID
1576+
|| channel_wait(channel, fd, channel->ch_timeout) == FAIL)
15181577
return NULL;
15191578
channel_read(channel, -1, "channel_read_block");
15201579
}
@@ -1533,7 +1592,7 @@ channel_read_block(channel_T *channel)
15331592
channel_read_json_block(channel_T *channel, int id, typval_T **rettv)
15341593
{
15351594
int more;
1536-
int fd;
1595+
sock_T fd;
15371596

15381597
ch_log(channel, "Reading JSON\n");
15391598
channel->ch_block_id = id;
@@ -1557,8 +1616,8 @@ channel_read_json_block(channel_T *channel, int id, typval_T **rettv)
15571616

15581617
/* Wait for up to the channel timeout. */
15591618
fd = get_read_fd(channel);
1560-
if (fd < 0 || channel_wait(channel, fd, channel->ch_timeout)
1561-
== FAIL)
1619+
if (fd == CHAN_FD_INVALID
1620+
|| channel_wait(channel, fd, channel->ch_timeout) == FAIL)
15621621
break;
15631622
channel_read(channel, -1, "channel_read_json_block");
15641623
}
@@ -1578,7 +1637,7 @@ channel_fd2channel(sock_T fd, int *whichp)
15781637
channel_T *channel;
15791638
int i;
15801639

1581-
if (fd >= 0)
1640+
if (fd != CHAN_FD_INVALID)
15821641
for (channel = first_channel; channel != NULL;
15831642
channel = channel->ch_next)
15841643
{
@@ -1607,19 +1666,19 @@ channel_send(channel_T *channel, char_u *buf, char *fun)
16071666
{
16081667
int len = (int)STRLEN(buf);
16091668
int res;
1610-
int fd = -1;
1669+
sock_T fd = CHAN_FD_INVALID;
16111670
int use_socket = FALSE;
16121671

1613-
if (channel->CH_SOCK >= 0)
1672+
if (channel->CH_SOCK != CHAN_FD_INVALID)
16141673
{
16151674
fd = channel->CH_SOCK;
16161675
use_socket = TRUE;
16171676
}
16181677
#if defined(CHANNEL_PIPES)
1619-
else if (channel->CH_IN >= 0)
1678+
else if (channel->CH_IN != CHAN_FD_INVALID)
16201679
fd = channel->CH_IN;
16211680
#endif
1622-
if (fd < 0)
1681+
if (fd == CHAN_FD_INVALID)
16231682
{
16241683
if (!channel->ch_error && fun != NULL)
16251684
{
@@ -1642,7 +1701,7 @@ channel_send(channel_T *channel, char_u *buf, char *fun)
16421701
if (use_socket)
16431702
res = sock_write(fd, buf, len);
16441703
else
1645-
res = write(fd, buf, len);
1704+
res = fd_write(fd, buf, len);
16461705
if (res != len)
16471706
{
16481707
if (!channel->ch_error && fun != NULL)
@@ -1680,7 +1739,7 @@ channel_poll_setup(int nfd_in, void *fds_in)
16801739
which = CHAN_SOCK;
16811740
# endif
16821741
{
1683-
if (channel->ch_pfd[which].ch_fd >= 0)
1742+
if (channel->ch_pfd[which].ch_fd != CHAN_FD_INVALID)
16841743
{
16851744
channel->ch_pfd[which].ch_poll_idx = nfd;
16861745
fds[nfd].fd = channel->ch_pfd[which].ch_fd;
@@ -1750,11 +1809,11 @@ channel_select_setup(int maxfd_in, void *rfds_in)
17501809
{
17511810
sock_T fd = channel->ch_pfd[which].ch_fd;
17521811

1753-
if (fd >= 0)
1812+
if (fd != CHAN_FD_INVALID)
17541813
{
1755-
FD_SET(fd, rfds);
1756-
if (maxfd < fd)
1757-
maxfd = fd;
1814+
FD_SET((int)fd, rfds);
1815+
if (maxfd < (int)fd)
1816+
maxfd = (int)fd;
17581817
}
17591818
}
17601819
}
@@ -1783,7 +1842,7 @@ channel_select_check(int ret_in, void *rfds_in)
17831842
{
17841843
sock_T fd = channel->ch_pfd[which].ch_fd;
17851844

1786-
if (ret > 0 && fd >= 0 && FD_ISSET(fd, rfds))
1845+
if (ret > 0 && fd != CHAN_FD_INVALID && FD_ISSET(fd, rfds))
17871846
{
17881847
channel_read(channel, which, "channel_select_check");
17891848
--ret;

0 commit comments

Comments
 (0)