Mercurial > vim
comparison src/channel.c @ 8114:4aea0b0aa714 v7.4.1351
commit https://github.com/vim/vim/commit/81661fb86801e6d6e5194b43dfd27d73fcc016ec
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Feb 18 22:23:34 2016 +0100
patch 7.4.1351
Problem: When the port isn't opened yet when ch_open() is called it may
fail instead of waiting for the specified time.
Solution: Loop when select() succeeds but when connect() failed. Also use
channel logging for jobs. Add ch_log().
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 18 Feb 2016 22:30:08 +0100 |
parents | 882ba5080c5c |
children | 39532ee7dd43 |
comparison
equal
deleted
inserted
replaced
8113:fd690d084aaf | 8114:4aea0b0aa714 |
---|---|
88 } | 88 } |
89 #endif | 89 #endif |
90 | 90 |
91 /* Log file opened with ch_logfile(). */ | 91 /* Log file opened with ch_logfile(). */ |
92 static FILE *log_fd = NULL; | 92 static FILE *log_fd = NULL; |
93 #ifdef FEAT_RELTIME | |
94 static proftime_T log_start; | |
95 #endif | |
93 | 96 |
94 void | 97 void |
95 ch_logfile(FILE *file) | 98 ch_logfile(FILE *file) |
96 { | 99 { |
97 if (log_fd != NULL) | 100 if (log_fd != NULL) |
98 fclose(log_fd); | 101 fclose(log_fd); |
99 log_fd = file; | 102 log_fd = file; |
100 if (log_fd != NULL) | 103 if (log_fd != NULL) |
104 { | |
101 fprintf(log_fd, "==== start log session ====\n"); | 105 fprintf(log_fd, "==== start log session ====\n"); |
106 #ifdef FEAT_RELTIME | |
107 profile_start(&log_start); | |
108 #endif | |
109 } | |
110 } | |
111 | |
112 int | |
113 ch_log_active() | |
114 { | |
115 return log_fd != NULL; | |
102 } | 116 } |
103 | 117 |
104 static void | 118 static void |
105 ch_log_lead(char *what, channel_T *ch) | 119 ch_log_lead(char *what, channel_T *ch) |
106 { | 120 { |
107 if (log_fd != NULL) | 121 if (log_fd != NULL) |
108 { | 122 { |
123 #ifdef FEAT_RELTIME | |
124 proftime_T log_now; | |
125 | |
126 profile_start(&log_now); | |
127 profile_sub(&log_now, &log_start); | |
128 fprintf(log_fd, "%s ", profile_msg(&log_now)); | |
129 #endif | |
109 if (ch != NULL) | 130 if (ch != NULL) |
110 fprintf(log_fd, "%son %d: ", what, ch->ch_id); | 131 fprintf(log_fd, "%son %d: ", what, ch->ch_id); |
111 else | 132 else |
112 fprintf(log_fd, "%s: ", what); | 133 fprintf(log_fd, "%s: ", what); |
113 } | 134 } |
114 } | 135 } |
115 | 136 |
116 static void | 137 void |
117 ch_log(channel_T *ch, char *msg) | 138 ch_log(channel_T *ch, char *msg) |
118 { | 139 { |
119 if (log_fd != NULL) | 140 if (log_fd != NULL) |
120 { | 141 { |
121 ch_log_lead("", ch); | 142 ch_log_lead("", ch); |
122 fputs(msg, log_fd); | 143 fputs(msg, log_fd); |
144 fputc('\n', log_fd); | |
123 fflush(log_fd); | 145 fflush(log_fd); |
124 } | 146 } |
125 } | 147 } |
126 | 148 |
127 static void | 149 static void |
129 { | 151 { |
130 if (log_fd != NULL) | 152 if (log_fd != NULL) |
131 { | 153 { |
132 ch_log_lead("", ch); | 154 ch_log_lead("", ch); |
133 fprintf(log_fd, msg, nr); | 155 fprintf(log_fd, msg, nr); |
156 fputc('\n', log_fd); | |
134 fflush(log_fd); | 157 fflush(log_fd); |
135 } | 158 } |
136 } | 159 } |
137 | 160 |
138 static void | 161 void |
139 ch_logs(channel_T *ch, char *msg, char *name) | 162 ch_logs(channel_T *ch, char *msg, char *name) |
140 { | 163 { |
141 if (log_fd != NULL) | 164 if (log_fd != NULL) |
142 { | 165 { |
143 ch_log_lead("", ch); | 166 ch_log_lead("", ch); |
144 fprintf(log_fd, msg, name); | 167 fprintf(log_fd, msg, name); |
168 fputc('\n', log_fd); | |
145 fflush(log_fd); | 169 fflush(log_fd); |
146 } | 170 } |
147 } | 171 } |
148 | 172 |
149 static void | 173 static void |
151 { | 175 { |
152 if (log_fd != NULL) | 176 if (log_fd != NULL) |
153 { | 177 { |
154 ch_log_lead("", ch); | 178 ch_log_lead("", ch); |
155 fprintf(log_fd, msg, name, nr); | 179 fprintf(log_fd, msg, name, nr); |
180 fputc('\n', log_fd); | |
156 fflush(log_fd); | 181 fflush(log_fd); |
157 } | 182 } |
158 } | 183 } |
159 | 184 |
160 static void | 185 static void |
162 { | 187 { |
163 if (log_fd != NULL) | 188 if (log_fd != NULL) |
164 { | 189 { |
165 ch_log_lead("ERR ", ch); | 190 ch_log_lead("ERR ", ch); |
166 fputs(msg, log_fd); | 191 fputs(msg, log_fd); |
192 fputc('\n', log_fd); | |
167 fflush(log_fd); | 193 fflush(log_fd); |
168 } | 194 } |
169 } | 195 } |
170 | 196 |
171 static void | 197 static void |
173 { | 199 { |
174 if (log_fd != NULL) | 200 if (log_fd != NULL) |
175 { | 201 { |
176 ch_log_lead("ERR ", ch); | 202 ch_log_lead("ERR ", ch); |
177 fprintf(log_fd, msg, nr); | 203 fprintf(log_fd, msg, nr); |
204 fputc('\n', log_fd); | |
178 fflush(log_fd); | 205 fflush(log_fd); |
179 } | 206 } |
180 } | 207 } |
181 | 208 |
182 static void | 209 static void |
184 { | 211 { |
185 if (log_fd != NULL) | 212 if (log_fd != NULL) |
186 { | 213 { |
187 ch_log_lead("ERR ", ch); | 214 ch_log_lead("ERR ", ch); |
188 fprintf(log_fd, msg, arg); | 215 fprintf(log_fd, msg, arg); |
216 fputc('\n', log_fd); | |
189 fflush(log_fd); | 217 fflush(log_fd); |
190 } | 218 } |
191 } | 219 } |
192 | 220 |
193 #ifdef _WIN32 | 221 #ifdef _WIN32 |
251 | 279 |
252 if (channel == NULL) | 280 if (channel == NULL) |
253 return NULL; | 281 return NULL; |
254 | 282 |
255 channel->ch_id = next_ch_id++; | 283 channel->ch_id = next_ch_id++; |
256 ch_log(channel, "Created channel\n"); | 284 ch_log(channel, "Created channel"); |
257 | 285 |
258 #ifdef CHANNEL_PIPES | 286 #ifdef CHANNEL_PIPES |
259 for (which = CHAN_SOCK; which <= CHAN_IN; ++which) | 287 for (which = CHAN_SOCK; which <= CHAN_IN; ++which) |
260 #else | 288 #else |
261 which = CHAN_SOCK; | 289 which = CHAN_SOCK; |
468 * Returns NULL for failure. | 496 * Returns NULL for failure. |
469 */ | 497 */ |
470 channel_T * | 498 channel_T * |
471 channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void)) | 499 channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void)) |
472 { | 500 { |
473 int sd; | 501 int sd = -1; |
474 struct sockaddr_in server; | 502 struct sockaddr_in server; |
475 struct hostent * host; | 503 struct hostent *host; |
476 #ifdef WIN32 | 504 #ifdef WIN32 |
477 u_short port = port_in; | 505 u_short port = port_in; |
478 u_long val = 1; | 506 u_long val = 1; |
479 #else | 507 #else |
480 int port = port_in; | 508 int port = port_in; |
509 struct timeval start_tv; | |
510 int so_error; | |
511 socklen_t so_error_len = sizeof(so_error); | |
481 #endif | 512 #endif |
482 channel_T *channel; | 513 channel_T *channel; |
483 int ret; | 514 int ret; |
484 | 515 |
485 #ifdef WIN32 | 516 #ifdef WIN32 |
487 #endif | 518 #endif |
488 | 519 |
489 channel = add_channel(); | 520 channel = add_channel(); |
490 if (channel == NULL) | 521 if (channel == NULL) |
491 { | 522 { |
492 ch_error(NULL, "Cannot allocate channel.\n"); | 523 ch_error(NULL, "Cannot allocate channel."); |
493 EMSG(_("E897: All channels are in use")); | |
494 return NULL; | |
495 } | |
496 | |
497 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) | |
498 { | |
499 ch_error(channel, "in socket() in channel_open().\n"); | |
500 PERROR("E898: socket() in channel_open()"); | |
501 channel_free(channel); | |
502 return NULL; | 524 return NULL; |
503 } | 525 } |
504 | 526 |
505 /* Get the server internet address and put into addr structure */ | 527 /* Get the server internet address and put into addr structure */ |
506 /* fill in the socket address structure and connect to server */ | 528 /* fill in the socket address structure and connect to server */ |
507 vim_memset((char *)&server, 0, sizeof(server)); | 529 vim_memset((char *)&server, 0, sizeof(server)); |
508 server.sin_family = AF_INET; | 530 server.sin_family = AF_INET; |
509 server.sin_port = htons(port); | 531 server.sin_port = htons(port); |
510 if ((host = gethostbyname(hostname)) == NULL) | 532 if ((host = gethostbyname(hostname)) == NULL) |
511 { | 533 { |
512 ch_error(channel, "in gethostbyname() in channel_open()\n"); | 534 ch_error(channel, "in gethostbyname() in channel_open()"); |
513 PERROR("E901: gethostbyname() in channel_open()"); | 535 PERROR("E901: gethostbyname() in channel_open()"); |
514 sock_close(sd); | |
515 channel_free(channel); | 536 channel_free(channel); |
516 return NULL; | 537 return NULL; |
517 } | 538 } |
518 memcpy((char *)&server.sin_addr, host->h_addr, host->h_length); | 539 memcpy((char *)&server.sin_addr, host->h_addr, host->h_length); |
519 | 540 |
520 if (waittime >= 0) | 541 #if defined(__APPLE__) && __APPLE__ == 1 |
521 { | 542 /* On Mac a zero timeout almost never works. At least wait one |
522 /* Make connect non-blocking. */ | 543 * millisecond. */ |
523 if ( | 544 if (waittime == 0) |
524 #ifdef _WIN32 | 545 waittime = 1; |
525 ioctlsocket(sd, FIONBIO, &val) < 0 | 546 #endif |
526 #else | 547 |
527 fcntl(sd, F_SETFL, O_NONBLOCK) < 0 | 548 /* |
528 #endif | 549 * For Unix we need to call connect() again after connect() failed. |
529 ) | 550 * On Win32 one time is sufficient. |
530 { | 551 */ |
531 SOCK_ERRNO; | 552 while (TRUE) |
532 ch_errorn(channel, "channel_open: Connect failed with errno %d\n", | 553 { |
533 errno); | 554 if (sd >= 0) |
534 sock_close(sd); | 555 sock_close(sd); |
556 sd = socket(AF_INET, SOCK_STREAM, 0); | |
557 if (sd == -1) | |
558 { | |
559 ch_error(channel, "in socket() in channel_open()."); | |
560 PERROR("E898: socket() in channel_open()"); | |
535 channel_free(channel); | 561 channel_free(channel); |
536 return NULL; | 562 return NULL; |
537 } | 563 } |
538 } | 564 |
539 | 565 if (waittime >= 0) |
540 /* Try connecting to the server. */ | 566 { |
541 ch_logsn(channel, "Connecting to %s port %d\n", hostname, port); | 567 /* Make connect() non-blocking. */ |
542 ret = connect(sd, (struct sockaddr *)&server, sizeof(server)); | 568 if ( |
543 SOCK_ERRNO; | 569 #ifdef _WIN32 |
544 if (ret < 0) | 570 ioctlsocket(sd, FIONBIO, &val) < 0 |
545 { | 571 #else |
546 if (errno != EWOULDBLOCK | 572 fcntl(sd, F_SETFL, O_NONBLOCK) < 0 |
573 #endif | |
574 ) | |
575 { | |
576 SOCK_ERRNO; | |
577 ch_errorn(channel, | |
578 "channel_open: Connect failed with errno %d", errno); | |
579 sock_close(sd); | |
580 channel_free(channel); | |
581 return NULL; | |
582 } | |
583 } | |
584 | |
585 /* Try connecting to the server. */ | |
586 ch_logsn(channel, "Connecting to %s port %d", hostname, port); | |
587 ret = connect(sd, (struct sockaddr *)&server, sizeof(server)); | |
588 | |
589 SOCK_ERRNO; | |
590 if (ret < 0) | |
591 { | |
592 if (errno != EWOULDBLOCK | |
593 && errno != ECONNREFUSED | |
594 | |
547 #ifdef EINPROGRESS | 595 #ifdef EINPROGRESS |
548 && errno != EINPROGRESS | 596 && errno != EINPROGRESS |
549 #endif | 597 #endif |
550 ) | 598 ) |
551 { | 599 { |
552 ch_errorn(channel, "channel_open: Connect failed with errno %d\n", | 600 ch_errorn(channel, |
553 errno); | 601 "channel_open: Connect failed with errno %d", errno); |
554 PERROR(_(e_cannot_connect)); | 602 PERROR(_(e_cannot_connect)); |
555 sock_close(sd); | 603 sock_close(sd); |
556 channel_free(channel); | 604 channel_free(channel); |
557 return NULL; | 605 return NULL; |
558 } | 606 } |
559 } | 607 } |
560 | 608 |
561 if (waittime >= 0 && ret < 0) | 609 /* If we don't block and connect() failed then try using select() to |
562 { | 610 * wait for the connection to be made. */ |
563 struct timeval tv; | 611 if (waittime >= 0 && ret < 0) |
564 fd_set wfds; | 612 { |
613 struct timeval tv; | |
614 fd_set wfds; | |
565 #if defined(__APPLE__) && __APPLE__ == 1 | 615 #if defined(__APPLE__) && __APPLE__ == 1 |
566 # define PASS_RFDS | 616 # define PASS_RFDS |
567 fd_set rfds; | 617 fd_set rfds; |
568 | 618 |
569 FD_ZERO(&rfds); | 619 FD_ZERO(&rfds); |
570 FD_SET(sd, &rfds); | 620 FD_SET(sd, &rfds); |
571 /* On Mac a zero timeout almost never works. At least wait one | 621 #endif |
572 * millisecond. */ | 622 FD_ZERO(&wfds); |
573 if (waittime == 0) | 623 FD_SET(sd, &wfds); |
574 waittime = 1; | 624 |
575 #endif | 625 tv.tv_sec = waittime / 1000; |
576 FD_ZERO(&wfds); | 626 tv.tv_usec = (waittime % 1000) * 1000; |
577 FD_SET(sd, &wfds); | 627 #ifndef WIN32 |
578 tv.tv_sec = waittime / 1000; | 628 gettimeofday(&start_tv, NULL); |
579 tv.tv_usec = (waittime % 1000) * 1000; | 629 #endif |
580 | 630 ch_logn(channel, |
581 ch_logn(channel, "Waiting for connection (timeout %d msec)...\n", | 631 "Waiting for connection (waittime %d msec)...", waittime); |
582 waittime); | 632 ret = select((int)sd + 1, |
583 ret = select((int)sd + 1, | |
584 #ifdef PASS_RFDS | 633 #ifdef PASS_RFDS |
585 &rfds, | 634 &rfds, |
586 #else | 635 #else |
587 NULL, | 636 NULL, |
588 #endif | 637 #endif |
589 &wfds, NULL, &tv); | 638 &wfds, NULL, &tv); |
590 | 639 |
591 if (ret < 0) | 640 if (ret < 0) |
592 { | 641 { |
593 SOCK_ERRNO; | 642 SOCK_ERRNO; |
594 ch_errorn(channel, "channel_open: Connect failed with errno %d\n", | 643 ch_errorn(channel, |
595 errno); | 644 "channel_open: Connect failed with errno %d", errno); |
596 PERROR(_(e_cannot_connect)); | 645 PERROR(_(e_cannot_connect)); |
597 sock_close(sd); | 646 sock_close(sd); |
598 channel_free(channel); | 647 channel_free(channel); |
599 return NULL; | 648 return NULL; |
600 } | 649 } |
601 #ifdef PASS_RFDS | 650 #ifdef PASS_RFDS |
602 if (ret == 0 && FD_ISSET(sd, &rfds) && FD_ISSET(sd, &wfds)) | 651 if (ret == 0 && FD_ISSET(sd, &rfds) && FD_ISSET(sd, &wfds)) |
603 { | 652 { |
604 /* For OS X, this implies error. See tcp(4). */ | 653 /* For OS X, this implies error. See tcp(4). */ |
605 ch_error(channel, "channel_open: Connect failed\n"); | 654 ch_error(channel, "channel_open: Connect failed"); |
606 EMSG(_(e_cannot_connect)); | 655 EMSG(_(e_cannot_connect)); |
607 sock_close(sd); | 656 sock_close(sd); |
608 channel_free(channel); | 657 channel_free(channel); |
609 return NULL; | 658 return NULL; |
610 } | 659 } |
611 #endif | 660 #endif |
612 if (!FD_ISSET(sd, &wfds)) | 661 #ifdef WIN32 |
613 { | 662 /* On Win32 select() is expected to work and wait for up to the |
614 /* don't give an error, we just timed out. */ | 663 * waittime for the socket to be open. */ |
615 ch_error(channel, "Connection timed out\n"); | 664 if (!FD_ISSET(sd, &wfds) || ret == 0) |
616 sock_close(sd); | 665 #else |
617 channel_free(channel); | 666 /* See socket(7) for the behavior on Linux-like systems: |
618 return NULL; | 667 * After putting the socket in non-blocking mode, connect() will |
619 } | 668 * return EINPROGRESS, select() will not wait (as if writing is |
620 ch_log(channel, "Connection made\n"); | 669 * possible), need to use getsockopt() to check if the socket is |
670 * actually open. */ | |
671 getsockopt(sd, SOL_SOCKET, SO_ERROR, &so_error, &so_error_len); | |
672 if (!FD_ISSET(sd, &wfds) || ret == 0 || so_error != 0) | |
673 #endif | |
674 { | |
675 #ifndef WIN32 | |
676 struct timeval end_tv; | |
677 long elapsed_msec; | |
678 | |
679 gettimeofday(&end_tv, NULL); | |
680 elapsed_msec = (end_tv.tv_sec - start_tv.tv_sec) * 1000 | |
681 + (end_tv.tv_usec - start_tv.tv_usec) / 1000; | |
682 if (waittime > 1 && elapsed_msec < waittime) | |
683 { | |
684 /* The port isn't ready but we also didn't get an error. | |
685 * This happens when the server didn't open the socket | |
686 * yet. Wait a bit and try again. */ | |
687 mch_delay(waittime < 50 ? (long)waittime : 50L, TRUE); | |
688 ui_breakcheck(); | |
689 if (!got_int) | |
690 { | |
691 /* reduce the waittime by the elapsed time and the 50 | |
692 * msec delay (or a bit more) */ | |
693 waittime -= elapsed_msec; | |
694 if (waittime > 50) | |
695 waittime -= 50; | |
696 else | |
697 waittime = 1; | |
698 continue; | |
699 } | |
700 /* we were interrupted, behave as if timed out */ | |
701 } | |
702 #endif | |
703 /* We timed out. */ | |
704 ch_error(channel, "Connection timed out"); | |
705 sock_close(sd); | |
706 channel_free(channel); | |
707 return NULL; | |
708 } | |
709 | |
710 ch_log(channel, "Connection made"); | |
711 break; | |
712 } | |
621 } | 713 } |
622 | 714 |
623 if (waittime >= 0) | 715 if (waittime >= 0) |
624 { | 716 { |
625 #ifdef _WIN32 | 717 #ifdef _WIN32 |
626 val = 0; | 718 val = 0; |
627 ioctlsocket(sd, FIONBIO, &val); | 719 ioctlsocket(sd, FIONBIO, &val); |
628 #else | 720 #else |
629 (void)fcntl(sd, F_SETFL, 0); | 721 (void)fcntl(sd, F_SETFL, 0); |
630 #endif | 722 #endif |
631 } | |
632 | |
633 /* Only retry for netbeans. TODO: can we use a waittime instead? */ | |
634 if (errno == ECONNREFUSED && close_cb != NULL) | |
635 { | |
636 sock_close(sd); | |
637 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) | |
638 { | |
639 SOCK_ERRNO; | |
640 ch_log(channel, "socket() retry in channel_open()\n"); | |
641 PERROR("E900: socket() retry in channel_open()"); | |
642 channel_free(channel); | |
643 return NULL; | |
644 } | |
645 if (connect(sd, (struct sockaddr *)&server, sizeof(server))) | |
646 { | |
647 int retries = 36; | |
648 int success = FALSE; | |
649 | |
650 SOCK_ERRNO; | |
651 while (retries-- && ((errno == ECONNREFUSED) | |
652 || (errno == EINTR))) | |
653 { | |
654 ch_log(channel, "retrying...\n"); | |
655 mch_delay(3000L, TRUE); | |
656 ui_breakcheck(); | |
657 if (got_int) | |
658 { | |
659 errno = EINTR; | |
660 break; | |
661 } | |
662 if (connect(sd, (struct sockaddr *)&server, | |
663 sizeof(server)) == 0) | |
664 { | |
665 success = TRUE; | |
666 break; | |
667 } | |
668 SOCK_ERRNO; | |
669 } | |
670 if (!success) | |
671 { | |
672 /* Get here when the server can't be found. */ | |
673 ch_error(channel, "Cannot connect to port after retry\n"); | |
674 PERROR(_("E899: Cannot connect to port after retry")); | |
675 sock_close(sd); | |
676 channel_free(channel); | |
677 return NULL; | |
678 } | |
679 } | |
680 } | 723 } |
681 | 724 |
682 channel->CH_SOCK = (sock_T)sd; | 725 channel->CH_SOCK = (sock_T)sd; |
683 channel->ch_close_cb = close_cb; | 726 channel->ch_close_cb = close_cb; |
684 | 727 |
1153 } | 1196 } |
1154 | 1197 |
1155 if (typetv->v_type != VAR_NUMBER) | 1198 if (typetv->v_type != VAR_NUMBER) |
1156 { | 1199 { |
1157 ch_error(channel, | 1200 ch_error(channel, |
1158 "Dropping message with invalid sequence number type\n"); | 1201 "Dropping message with invalid sequence number type"); |
1159 free_tv(listtv); | 1202 free_tv(listtv); |
1160 return FALSE; | 1203 return FALSE; |
1161 } | 1204 } |
1162 seq_nr = typetv->vval.v_number; | 1205 seq_nr = typetv->vval.v_number; |
1163 } | 1206 } |
1221 /* invoke the one-time callback with the matching nr */ | 1264 /* invoke the one-time callback with the matching nr */ |
1222 while (item != NULL) | 1265 while (item != NULL) |
1223 { | 1266 { |
1224 if (item->cq_seq_nr == seq_nr) | 1267 if (item->cq_seq_nr == seq_nr) |
1225 { | 1268 { |
1226 ch_log(channel, "Invoking one-time callback\n"); | 1269 ch_log(channel, "Invoking one-time callback"); |
1227 /* Remove the item from the list first, if the callback | 1270 /* Remove the item from the list first, if the callback |
1228 * invokes ch_close() the list will be cleared. */ | 1271 * invokes ch_close() the list will be cleared. */ |
1229 remove_cb_node(head, item); | 1272 remove_cb_node(head, item); |
1230 invoke_callback(channel, item->cq_callback, argv); | 1273 invoke_callback(channel, item->cq_callback, argv); |
1231 vim_free(item->cq_callback); | 1274 vim_free(item->cq_callback); |
1234 break; | 1277 break; |
1235 } | 1278 } |
1236 item = item->cq_next; | 1279 item = item->cq_next; |
1237 } | 1280 } |
1238 if (!done) | 1281 if (!done) |
1239 ch_log(channel, "Dropping message without callback\n"); | 1282 ch_log(channel, "Dropping message without callback"); |
1240 } | 1283 } |
1241 else if (channel->ch_callback != NULL) | 1284 else if (channel->ch_callback != NULL) |
1242 { | 1285 { |
1243 /* invoke the channel callback */ | 1286 /* invoke the channel callback */ |
1244 ch_log(channel, "Invoking channel callback\n"); | 1287 ch_log(channel, "Invoking channel callback"); |
1245 invoke_callback(channel, channel->ch_callback, argv); | 1288 invoke_callback(channel, channel->ch_callback, argv); |
1246 } | 1289 } |
1247 else | 1290 else |
1248 ch_log(channel, "Dropping message\n"); | 1291 ch_log(channel, "Dropping message"); |
1249 | 1292 |
1250 if (listtv != NULL) | 1293 if (listtv != NULL) |
1251 free_tv(listtv); | 1294 free_tv(listtv); |
1252 vim_free(msg); | 1295 vim_free(msg); |
1253 | 1296 |
1302 * This does not trigger the close callback. | 1345 * This does not trigger the close callback. |
1303 */ | 1346 */ |
1304 void | 1347 void |
1305 channel_close(channel_T *channel) | 1348 channel_close(channel_T *channel) |
1306 { | 1349 { |
1307 ch_log(channel, "Closing channel\n"); | 1350 ch_log(channel, "Closing channel"); |
1308 | 1351 |
1309 #ifdef FEAT_GUI | 1352 #ifdef FEAT_GUI |
1310 channel_gui_unregister(channel); | 1353 channel_gui_unregister(channel); |
1311 #endif | 1354 #endif |
1312 | 1355 |
1469 struct timeval tval; | 1512 struct timeval tval; |
1470 fd_set rfds; | 1513 fd_set rfds; |
1471 int ret; | 1514 int ret; |
1472 | 1515 |
1473 if (timeout > 0) | 1516 if (timeout > 0) |
1474 ch_logn(channel, "Waiting for up to %d msec\n", timeout); | 1517 ch_logn(channel, "Waiting for up to %d msec", timeout); |
1475 | 1518 |
1476 | 1519 |
1477 # ifdef WIN32 | 1520 # ifdef WIN32 |
1478 if (channel->CH_SOCK == CHAN_FD_INVALID) | 1521 if (channel->CH_SOCK == CHAN_FD_INVALID) |
1479 { | 1522 { |
1509 if (ret == -1 && errno == EINTR) | 1552 if (ret == -1 && errno == EINTR) |
1510 continue; | 1553 continue; |
1511 # endif | 1554 # endif |
1512 if (ret <= 0) | 1555 if (ret <= 0) |
1513 { | 1556 { |
1514 ch_log(channel, "Nothing to read\n"); | 1557 ch_log(channel, "Nothing to read"); |
1515 return FAIL; | 1558 return FAIL; |
1516 } | 1559 } |
1517 break; | 1560 break; |
1518 } | 1561 } |
1519 #else | 1562 #else |
1520 # ifdef HAVE_POLL | 1563 # ifdef HAVE_POLL |
1521 struct pollfd fds; | 1564 struct pollfd fds; |
1522 | 1565 |
1523 if (timeout > 0) | 1566 if (timeout > 0) |
1524 ch_logn(channel, "Waiting for %d msec\n", timeout); | 1567 ch_logn(channel, "Waiting for %d msec", timeout); |
1525 fds.fd = fd; | 1568 fds.fd = fd; |
1526 fds.events = POLLIN; | 1569 fds.events = POLLIN; |
1527 if (poll(&fds, 1, timeout) <= 0) | 1570 if (poll(&fds, 1, timeout) <= 0) |
1528 { | 1571 { |
1529 ch_log(channel, "Nothing to read\n"); | 1572 ch_log(channel, "Nothing to read"); |
1530 return FAIL; | 1573 return FAIL; |
1531 } | 1574 } |
1532 # endif | 1575 # endif |
1533 #endif | 1576 #endif |
1534 return OK; | 1577 return OK; |
1556 return channel->CH_SOCK; | 1599 return channel->CH_SOCK; |
1557 #if defined(CHANNEL_PIPES) | 1600 #if defined(CHANNEL_PIPES) |
1558 if (channel->CH_OUT != CHAN_FD_INVALID) | 1601 if (channel->CH_OUT != CHAN_FD_INVALID) |
1559 return channel->CH_OUT; | 1602 return channel->CH_OUT; |
1560 #endif | 1603 #endif |
1561 ch_error(channel, "channel_read() called while socket is closed\n"); | 1604 ch_error(channel, "channel_read() called while socket is closed"); |
1562 return CHAN_FD_INVALID; | 1605 return CHAN_FD_INVALID; |
1563 } | 1606 } |
1564 | 1607 |
1565 /* | 1608 /* |
1566 * Read from channel "channel" for as long as there is something to read. | 1609 * Read from channel "channel" for as long as there is something to read. |
1635 * -> autocmd triggered while processing the netbeans cmd | 1678 * -> autocmd triggered while processing the netbeans cmd |
1636 * -> ui_breakcheck | 1679 * -> ui_breakcheck |
1637 * -> gui event loop or select loop | 1680 * -> gui event loop or select loop |
1638 * -> channel_read() | 1681 * -> channel_read() |
1639 */ | 1682 */ |
1640 ch_errors(channel, "%s(): Cannot read\n", func); | 1683 ch_errors(channel, "%s(): Cannot read", func); |
1641 channel_save(channel, (char_u *)DETACH_MSG, (int)STRLEN(DETACH_MSG)); | 1684 channel_save(channel, (char_u *)DETACH_MSG, (int)STRLEN(DETACH_MSG)); |
1642 | 1685 |
1643 /* TODO: When reading from stdout is not possible, should we try to | 1686 /* TODO: When reading from stdout is not possible, should we try to |
1644 * keep stdin and stderr open? Probably not, assume the other side | 1687 * keep stdin and stderr open? Probably not, assume the other side |
1645 * has died. */ | 1688 * has died. */ |
1647 if (channel->ch_close_cb != NULL) | 1690 if (channel->ch_close_cb != NULL) |
1648 (*channel->ch_close_cb)(); | 1691 (*channel->ch_close_cb)(); |
1649 | 1692 |
1650 if (len < 0) | 1693 if (len < 0) |
1651 { | 1694 { |
1652 ch_error(channel, "channel_read(): cannot read from channel\n"); | 1695 ch_error(channel, "channel_read(): cannot read from channel"); |
1653 PERROR(_("E896: read from channel")); | 1696 PERROR(_("E896: read from channel")); |
1654 } | 1697 } |
1655 } | 1698 } |
1656 | 1699 |
1657 #if defined(CH_HAS_GUI) && defined(FEAT_GUI_GTK) | 1700 #if defined(CH_HAS_GUI) && defined(FEAT_GUI_GTK) |
1675 char_u *msg; | 1718 char_u *msg; |
1676 ch_mode_T mode = channel->ch_mode; | 1719 ch_mode_T mode = channel->ch_mode; |
1677 sock_T fd = get_read_fd(channel); | 1720 sock_T fd = get_read_fd(channel); |
1678 char_u *nl; | 1721 char_u *nl; |
1679 | 1722 |
1680 ch_logsn(channel, "Blocking %s read, timeout: %d msec\n", | 1723 ch_logsn(channel, "Blocking %s read, timeout: %d msec", |
1681 mode == MODE_RAW ? "RAW" : "NL", channel->ch_timeout); | 1724 mode == MODE_RAW ? "RAW" : "NL", channel->ch_timeout); |
1682 | 1725 |
1683 while (TRUE) | 1726 while (TRUE) |
1684 { | 1727 { |
1685 buf = channel_peek(channel); | 1728 buf = channel_peek(channel); |
1716 msg = vim_strnsave(buf, (int)(nl - buf)); | 1759 msg = vim_strnsave(buf, (int)(nl - buf)); |
1717 mch_memmove(buf, nl + 1, STRLEN(nl + 1) + 1); | 1760 mch_memmove(buf, nl + 1, STRLEN(nl + 1) + 1); |
1718 } | 1761 } |
1719 } | 1762 } |
1720 if (log_fd != NULL) | 1763 if (log_fd != NULL) |
1721 ch_logn(channel, "Returning %d bytes\n", (int)STRLEN(msg)); | 1764 ch_logn(channel, "Returning %d bytes", (int)STRLEN(msg)); |
1722 return msg; | 1765 return msg; |
1723 } | 1766 } |
1724 | 1767 |
1725 /* | 1768 /* |
1726 * Read one JSON message with ID "id" from channel "channel" and store the | 1769 * Read one JSON message with ID "id" from channel "channel" and store the |
1731 channel_read_json_block(channel_T *channel, int id, typval_T **rettv) | 1774 channel_read_json_block(channel_T *channel, int id, typval_T **rettv) |
1732 { | 1775 { |
1733 int more; | 1776 int more; |
1734 sock_T fd; | 1777 sock_T fd; |
1735 | 1778 |
1736 ch_log(channel, "Reading JSON\n"); | 1779 ch_log(channel, "Reading JSON"); |
1737 channel->ch_block_id = id; | 1780 channel->ch_block_id = id; |
1738 for (;;) | 1781 for (;;) |
1739 { | 1782 { |
1740 more = channel_parse_json(channel); | 1783 more = channel_parse_json(channel); |
1741 | 1784 |
1819 #endif | 1862 #endif |
1820 if (fd == CHAN_FD_INVALID) | 1863 if (fd == CHAN_FD_INVALID) |
1821 { | 1864 { |
1822 if (!channel->ch_error && fun != NULL) | 1865 if (!channel->ch_error && fun != NULL) |
1823 { | 1866 { |
1824 ch_errors(channel, "%s(): write while not connected\n", fun); | 1867 ch_errors(channel, "%s(): write while not connected", fun); |
1825 EMSG2("E630: %s(): write while not connected", fun); | 1868 EMSG2("E630: %s(): write while not connected", fun); |
1826 } | 1869 } |
1827 channel->ch_error = TRUE; | 1870 channel->ch_error = TRUE; |
1828 return FAIL; | 1871 return FAIL; |
1829 } | 1872 } |
1843 res = fd_write(fd, (char *)buf, len); | 1886 res = fd_write(fd, (char *)buf, len); |
1844 if (res != len) | 1887 if (res != len) |
1845 { | 1888 { |
1846 if (!channel->ch_error && fun != NULL) | 1889 if (!channel->ch_error && fun != NULL) |
1847 { | 1890 { |
1848 ch_errors(channel, "%s(): write failed\n", fun); | 1891 ch_errors(channel, "%s(): write failed", fun); |
1849 EMSG2("E631: %s(): write failed", fun); | 1892 EMSG2("E631: %s(): write failed", fun); |
1850 } | 1893 } |
1851 channel->ch_error = TRUE; | 1894 channel->ch_error = TRUE; |
1852 return FAIL; | 1895 return FAIL; |
1853 } | 1896 } |