comparison src/channel.c @ 7935:3f2e0b62003d v7.4.1263

commit https://github.com/vim/vim/commit/4d919d748e4e435edb135aa5ccf6ee7de9212023 Author: Bram Moolenaar <Bram@vim.org> Date: Fri Feb 5 22:36:41 2016 +0100 patch 7.4.1263 Problem: ch_open() hangs when the server isn't running. Solution: Add a timeout. Use a dict to pass arguments. (Yasuhiro Matsumoto)
author Christian Brabandt <cb@256bit.org>
date Fri, 05 Feb 2016 22:45:06 +0100
parents 1f0743f4f88f
children 2e905dfc6999
comparison
equal deleted inserted replaced
7934:1aab88611034 7935:3f2e0b62003d
40 /* WinSock API is separated from C API, thus we can't use read(), write(), 40 /* WinSock API is separated from C API, thus we can't use read(), write(),
41 * errno... */ 41 * errno... */
42 # define SOCK_ERRNO errno = WSAGetLastError() 42 # define SOCK_ERRNO errno = WSAGetLastError()
43 # undef ECONNREFUSED 43 # undef ECONNREFUSED
44 # define ECONNREFUSED WSAECONNREFUSED 44 # define ECONNREFUSED WSAECONNREFUSED
45 # undef EWOULDBLOCK
46 # define EWOULDBLOCK WSAEWOULDBLOCK
45 # ifdef EINTR 47 # ifdef EINTR
46 # undef EINTR 48 # undef EINTR
47 # endif 49 # endif
48 # define EINTR WSAEINTR 50 # define EINTR WSAEINTR
49 # define sock_write(sd, buf, len) send(sd, buf, len, 0) 51 # define sock_write(sd, buf, len) send(sd, buf, len, 0)
117 char_u *ch_callback; /* function to call when a msg is not handled */ 119 char_u *ch_callback; /* function to call when a msg is not handled */
118 cbq_T ch_cb_head; /* dummy node for pre-request callbacks */ 120 cbq_T ch_cb_head; /* dummy node for pre-request callbacks */
119 121
120 int ch_json_mode; /* TRUE for a json channel */ 122 int ch_json_mode; /* TRUE for a json channel */
121 jsonq_T ch_json_head; /* dummy node, header for circular queue */ 123 jsonq_T ch_json_head; /* dummy node, header for circular queue */
124
125 int ch_timeout; /* request timeout in msec */
122 } channel_T; 126 } channel_T;
123 127
124 /* 128 /*
125 * Information about all channels. 129 * Information about all channels.
126 * There can be gaps for closed channels, they will be reused later. 130 * There can be gaps for closed channels, they will be reused later.
130 134
131 /* 135 /*
132 * TODO: open debug file when desired. 136 * TODO: open debug file when desired.
133 */ 137 */
134 FILE *debugfd = NULL; 138 FILE *debugfd = NULL;
139
140 #ifdef _WIN32
141 # undef PERROR
142 # define PERROR(msg) (void)emsg3((char_u *)"%s: %s", \
143 (char_u *)msg, (char_u *)strerror_win32(errno))
144
145 static char *
146 strerror_win32(int eno)
147 {
148 static LPVOID msgbuf = NULL;
149 char_u *ptr;
150
151 if (msgbuf)
152 LocalFree(msgbuf);
153 FormatMessage(
154 FORMAT_MESSAGE_ALLOCATE_BUFFER |
155 FORMAT_MESSAGE_FROM_SYSTEM |
156 FORMAT_MESSAGE_IGNORE_INSERTS,
157 NULL,
158 eno,
159 MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
160 (LPTSTR) &msgbuf,
161 0,
162 NULL);
163 /* chomp \r or \n */
164 for (ptr = (char_u *)msgbuf; *ptr; ptr++)
165 switch (*ptr)
166 {
167 case '\r':
168 STRMOVE(ptr, ptr + 1);
169 ptr--;
170 break;
171 case '\n':
172 if (*(ptr + 1) == '\0')
173 *ptr = '\0';
174 else
175 *ptr = ' ';
176 break;
177 }
178 return msgbuf;
179 }
180 #endif
135 181
136 /* 182 /*
137 * Add a new channel slot, return the index. 183 * Add a new channel slot, return the index.
138 * The channel isn't actually used into ch_fd is set >= 0; 184 * The channel isn't actually used into ch_fd is set >= 0;
139 * Returns -1 if all channels are in use. 185 * Returns -1 if all channels are in use.
179 ch->ch_head.prev = &ch->ch_head; 225 ch->ch_head.prev = &ch->ch_head;
180 ch->ch_cb_head.next = &ch->ch_cb_head; 226 ch->ch_cb_head.next = &ch->ch_cb_head;
181 ch->ch_cb_head.prev = &ch->ch_cb_head; 227 ch->ch_cb_head.prev = &ch->ch_cb_head;
182 ch->ch_json_head.next = &ch->ch_json_head; 228 ch->ch_json_head.next = &ch->ch_json_head;
183 ch->ch_json_head.prev = &ch->ch_json_head; 229 ch->ch_json_head.prev = &ch->ch_json_head;
230
231 ch->ch_timeout = 2000;
184 232
185 return channel_count++; 233 return channel_count++;
186 } 234 }
187 235
188 #if defined(FEAT_GUI) || defined(PROTO) 236 #if defined(FEAT_GUI) || defined(PROTO)
301 * Open a channel to "hostname":"port". 349 * Open a channel to "hostname":"port".
302 * Returns the channel number for success. 350 * Returns the channel number for success.
303 * Returns a negative number for failure. 351 * Returns a negative number for failure.
304 */ 352 */
305 int 353 int
306 channel_open(char *hostname, int port_in, void (*close_cb)(void)) 354 channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
307 { 355 {
308 int sd; 356 int sd;
309 struct sockaddr_in server; 357 struct sockaddr_in server;
310 struct hostent * host; 358 struct hostent * host;
311 #ifdef WIN32 359 #ifdef WIN32
312 u_short port = port_in; 360 u_short port = port_in;
361 u_long val = 1;
313 #else 362 #else
314 int port = port_in; 363 int port = port_in;
315 #endif 364 #endif
316 int idx; 365 int idx;
366 int ret;
317 367
318 #ifdef WIN32 368 #ifdef WIN32
319 channel_init_winsock(); 369 channel_init_winsock();
320 #endif 370 #endif
321 371
346 sock_close(sd); 396 sock_close(sd);
347 return -1; 397 return -1;
348 } 398 }
349 memcpy((char *)&server.sin_addr, host->h_addr, host->h_length); 399 memcpy((char *)&server.sin_addr, host->h_addr, host->h_length);
350 400
351 /* Connect to server */ 401 if (waittime >= 0)
352 if (connect(sd, (struct sockaddr *)&server, sizeof(server))) 402 {
353 { 403 /* Make connect non-blocking. */
354 SOCK_ERRNO; 404 if (
355 CHERROR("channel_open: Connect failed with errno %d\n", errno); 405 #ifdef _WIN32
356 if (errno == ECONNREFUSED) 406 ioctlsocket(sd, FIONBIO, &val) < 0
357 { 407 #else
408 fcntl(sd, F_SETFL, O_NONBLOCK) < 0
409 #endif
410 )
411 {
412 SOCK_ERRNO;
413 CHERROR("channel_open: Connect failed with errno %d\n", errno);
358 sock_close(sd); 414 sock_close(sd);
359 if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1) 415 return -1;
360 { 416 }
361 SOCK_ERRNO; 417 }
362 CHERROR("socket() retry in channel_open()\n", ""); 418
363 PERROR("E900: socket() retry in channel_open()"); 419 /* Try connecting to the server. */
364 return -1; 420 ret = connect(sd, (struct sockaddr *)&server, sizeof(server));
365 } 421 SOCK_ERRNO;
366 if (connect(sd, (struct sockaddr *)&server, sizeof(server))) 422 if (ret < 0)
367 { 423 {
368 int retries = 36; 424 if (errno != EWOULDBLOCK && errno != EINPROGRESS)
369 int success = FALSE; 425 {
370 426 CHERROR("channel_open: Connect failed with errno %d\n", errno);
371 SOCK_ERRNO;
372 while (retries-- && ((errno == ECONNREFUSED)
373 || (errno == EINTR)))
374 {
375 CHERROR("retrying...\n", "");
376 mch_delay(3000L, TRUE);
377 ui_breakcheck();
378 if (got_int)
379 {
380 errno = EINTR;
381 break;
382 }
383 if (connect(sd, (struct sockaddr *)&server,
384 sizeof(server)) == 0)
385 {
386 success = TRUE;
387 break;
388 }
389 SOCK_ERRNO;
390 }
391 if (!success)
392 {
393 /* Get here when the server can't be found. */
394 CHERROR("Cannot connect to port after retry\n", "");
395 PERROR(_("E899: Cannot connect to port after retry2"));
396 sock_close(sd);
397 return -1;
398 }
399 }
400 }
401 else
402 {
403 CHERROR("Cannot connect to port\n", ""); 427 CHERROR("Cannot connect to port\n", "");
404 PERROR(_("E902: Cannot connect to port")); 428 PERROR(_("E902: Cannot connect to port"));
405 sock_close(sd); 429 sock_close(sd);
406 return -1; 430 return -1;
407 } 431 }
408 } 432 }
409 433
434 if (waittime >= 0)
435 {
436 struct timeval tv;
437 fd_set rfds, wfds;
438
439 FD_ZERO(&rfds);
440 FD_ZERO(&wfds);
441 FD_SET(sd, &rfds);
442 FD_SET(sd, &wfds);
443 tv.tv_sec = waittime;
444 tv.tv_usec = 0;
445 ret = select((int)sd+1, &rfds, &wfds, NULL, &tv);
446 if (ret < 0)
447 {
448 SOCK_ERRNO;
449 CHERROR("channel_open: Connect failed with errno %d\n", errno);
450 CHERROR("Cannot connect to port\n", "");
451 PERROR(_("E902: Cannot connect to port"));
452 sock_close(sd);
453 return -1;
454 }
455 if (!FD_ISSET(sd, &rfds) && !FD_ISSET(sd, &wfds))
456 {
457 errno = ECONNREFUSED;
458 CHERROR("Cannot connect to port\n", "");
459 PERROR(_("E902: Cannot connect to port"));
460 sock_close(sd);
461 return -1;
462 }
463
464 #ifdef _WIN32
465 val = 0;
466 ioctlsocket(sd, FIONBIO, &val);
467 #else
468 fcntl(sd, F_SETFL, 0);
469 #endif
470 }
471
472 if (errno == ECONNREFUSED)
473 {
474 sock_close(sd);
475 if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
476 {
477 SOCK_ERRNO;
478 CHERROR("socket() retry in channel_open()\n", "");
479 PERROR("E900: socket() retry in channel_open()");
480 return -1;
481 }
482 if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
483 {
484 int retries = 36;
485 int success = FALSE;
486
487 SOCK_ERRNO;
488 while (retries-- && ((errno == ECONNREFUSED)
489 || (errno == EINTR)))
490 {
491 CHERROR("retrying...\n", "");
492 mch_delay(3000L, TRUE);
493 ui_breakcheck();
494 if (got_int)
495 {
496 errno = EINTR;
497 break;
498 }
499 if (connect(sd, (struct sockaddr *)&server,
500 sizeof(server)) == 0)
501 {
502 success = TRUE;
503 break;
504 }
505 SOCK_ERRNO;
506 }
507 if (!success)
508 {
509 /* Get here when the server can't be found. */
510 CHERROR("Cannot connect to port after retry\n", "");
511 PERROR(_("E899: Cannot connect to port after retry2"));
512 sock_close(sd);
513 return -1;
514 }
515 }
516 }
517
410 channels[idx].ch_fd = sd; 518 channels[idx].ch_fd = sd;
411 channels[idx].ch_close_cb = close_cb; 519 channels[idx].ch_close_cb = close_cb;
412 520
413 #ifdef FEAT_GUI 521 #ifdef FEAT_GUI
414 channel_gui_register(idx); 522 channel_gui_register(idx);
422 */ 530 */
423 void 531 void
424 channel_set_json_mode(int idx, int json_mode) 532 channel_set_json_mode(int idx, int json_mode)
425 { 533 {
426 channels[idx].ch_json_mode = json_mode; 534 channels[idx].ch_json_mode = json_mode;
535 }
536
537 /*
538 * Set the read timeout of channel "idx".
539 */
540 void
541 channel_set_timeout(int idx, int timeout)
542 {
543 channels[idx].ch_timeout = timeout;
427 } 544 }
428 545
429 /* 546 /*
430 * Set the callback for channel "idx". 547 * Set the callback for channel "idx".
431 */ 548 */
896 #ifdef FEAT_GUI 1013 #ifdef FEAT_GUI
897 channel_gui_unregister(idx); 1014 channel_gui_unregister(idx);
898 #endif 1015 #endif
899 vim_free(channel->ch_callback); 1016 vim_free(channel->ch_callback);
900 channel->ch_callback = NULL; 1017 channel->ch_callback = NULL;
1018 channel->ch_timeout = 2000;
901 1019
902 while (channel_peek(idx) != NULL) 1020 while (channel_peek(idx) != NULL)
903 vim_free(channel_get(idx)); 1021 vim_free(channel_get(idx));
904 1022
905 cbhead = &channel->ch_cb_head; 1023 cbhead = &channel->ch_cb_head;
1146 char_u * 1264 char_u *
1147 channel_read_block(int idx) 1265 channel_read_block(int idx)
1148 { 1266 {
1149 if (channel_peek(idx) == NULL) 1267 if (channel_peek(idx) == NULL)
1150 { 1268 {
1151 /* Wait for up to 2 seconds. 1269 /* Wait for up to the channel timeout. */
1152 * TODO: use timeout set on the channel. */ 1270 if (channel_wait(channels[idx].ch_fd, channels[idx].ch_timeout) == FAIL)
1153 if (channel_wait(channels[idx].ch_fd, 2000) == FAIL)
1154 return NULL; 1271 return NULL;
1155 channel_read(idx); 1272 channel_read(idx);
1156 } 1273 }
1157 1274
1158 return channel_get_all(idx); 1275 return channel_get_all(idx);
1159 } 1276 }
1160 1277
1161 /* 1278 /*
1162 * Read one JSON message from channel "ch_idx" with ID "id" and store the 1279 * Read one JSON message from channel "ch_idx" with ID "id" and store the
1163 * result in "rettv". 1280 * result in "rettv".
1164 * Blocks until the message is received. 1281 * Blocks until the message is received or the timeout is reached.
1165 */ 1282 */
1166 int 1283 int
1167 channel_read_json_block(int ch_idx, int id, typval_T **rettv) 1284 channel_read_json_block(int ch_idx, int id, typval_T **rettv)
1168 { 1285 {
1169 int more; 1286 int more;
1181 /* Handle any other messages in the queue. If done some more 1298 /* Handle any other messages in the queue. If done some more
1182 * messages may have arrived. */ 1299 * messages may have arrived. */
1183 if (channel_parse_messages()) 1300 if (channel_parse_messages())
1184 continue; 1301 continue;
1185 1302
1186 /* Wait for up to 2 seconds. 1303 /* Wait for up to the channel timeout. */
1187 * TODO: use timeout set on the channel. */
1188 if (channels[ch_idx].ch_fd < 0 1304 if (channels[ch_idx].ch_fd < 0
1189 || channel_wait(channels[ch_idx].ch_fd, 2000) == FAIL) 1305 || channel_wait(channels[ch_idx].ch_fd,
1306 channels[ch_idx].ch_timeout) == FAIL)
1190 break; 1307 break;
1191 channel_read(ch_idx); 1308 channel_read(ch_idx);
1192 } 1309 }
1193 } 1310 }
1194 return FAIL; 1311 return FAIL;