comparison src/channel.c @ 9007:d5c6f1c5cd28 v7.4.1789

commit https://github.com/vim/vim/commit/437905c25d4cedfa16d0f87392e4a000d22362b7 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Apr 26 19:01:05 2016 +0200 patch 7.4.1789 Problem: Cannot use ch_read() in the close callback. Solution: Do not discard the channel if there is readahead. Do not discard readahead if there is a close callback.
author Christian Brabandt <cb@256bit.org>
date Tue, 26 Apr 2016 19:15:06 +0200
parents 072556995a8e
children 72a597e9e36d
comparison
equal deleted inserted replaced
9006:ef8e23332fa8 9007:d5c6f1c5cd28
2101 in_part->ch_buf_bot = buffer->b_ml.ml_line_count; 2101 in_part->ch_buf_bot = buffer->b_ml.ml_line_count;
2102 } 2102 }
2103 } 2103 }
2104 } 2104 }
2105 2105
2106 static void
2107 drop_messages(channel_T *channel, int part)
2108 {
2109 char_u *msg;
2110
2111 while ((msg = channel_get(channel, part)) != NULL)
2112 {
2113 ch_logs(channel, "Dropping message '%s'", (char *)msg);
2114 vim_free(msg);
2115 }
2116 }
2117
2106 /* 2118 /*
2107 * Invoke a callback for "channel"/"part" if needed. 2119 * Invoke a callback for "channel"/"part" if needed.
2108 * This does not redraw but sets channel_need_redraw when redraw is needed. 2120 * This does not redraw but sets channel_need_redraw when redraw is needed.
2109 * Return TRUE when a message was handled, there might be another one. 2121 * Return TRUE when a message was handled, there might be another one.
2110 */ 2122 */
2200 else 2212 else
2201 { 2213 {
2202 /* If there is no callback or buffer drop the message. */ 2214 /* If there is no callback or buffer drop the message. */
2203 if (callback == NULL && buffer == NULL) 2215 if (callback == NULL && buffer == NULL)
2204 { 2216 {
2205 while ((msg = channel_get(channel, part)) != NULL) 2217 /* If there is a close callback it may use ch_read() to get the
2206 { 2218 * messages. */
2207 ch_logs(channel, "Dropping message '%s'", (char *)msg); 2219 if (channel->ch_close_cb == NULL)
2208 vim_free(msg); 2220 drop_messages(channel, part);
2209 }
2210 return FALSE; 2221 return FALSE;
2211 } 2222 }
2212 2223
2213 if (ch_mode == MODE_NL) 2224 if (ch_mode == MODE_NL)
2214 { 2225 {
2324 || channel->CH_OUT_FD != INVALID_FD 2335 || channel->CH_OUT_FD != INVALID_FD
2325 || channel->CH_ERR_FD != INVALID_FD); 2336 || channel->CH_ERR_FD != INVALID_FD);
2326 } 2337 }
2327 2338
2328 /* 2339 /*
2340 * Return TRUE if "channel" has JSON or other typeahead.
2341 */
2342 static int
2343 channel_has_readahead(channel_T *channel, int part)
2344 {
2345 ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
2346
2347 if (ch_mode == MODE_JSON || ch_mode == MODE_JS)
2348 {
2349 jsonq_T *head = &channel->ch_part[part].ch_json_head;
2350 jsonq_T *item = head->jq_next;
2351
2352 return item != NULL;
2353 }
2354 return channel_peek(channel, part) != NULL;
2355 }
2356
2357 /*
2329 * Return a string indicating the status of the channel. 2358 * Return a string indicating the status of the channel.
2330 */ 2359 */
2331 char * 2360 char *
2332 channel_status(channel_T *channel) 2361 channel_status(channel_T *channel)
2333 { 2362 {
2363 int part;
2364 int has_readahead = FALSE;
2365
2334 if (channel == NULL) 2366 if (channel == NULL)
2335 return "fail"; 2367 return "fail";
2336 if (channel_is_open(channel)) 2368 if (channel_is_open(channel))
2337 return "open"; 2369 return "open";
2370 for (part = PART_SOCK; part <= PART_ERR; ++part)
2371 if (channel_has_readahead(channel, part))
2372 {
2373 has_readahead = TRUE;
2374 break;
2375 }
2376
2377 if (has_readahead)
2378 return "buffered";
2338 return "closed"; 2379 return "closed";
2339 } 2380 }
2340 2381
2341 static void 2382 static void
2342 channel_part_info(channel_T *channel, dict_T *dict, char *name, int part) 2383 channel_part_info(channel_T *channel, dict_T *dict, char *name, int part)
2456 /* the callback is only called once */ 2497 /* the callback is only called once */
2457 vim_free(channel->ch_close_cb); 2498 vim_free(channel->ch_close_cb);
2458 channel->ch_close_cb = NULL; 2499 channel->ch_close_cb = NULL;
2459 partial_unref(channel->ch_close_partial); 2500 partial_unref(channel->ch_close_partial);
2460 channel->ch_close_partial = NULL; 2501 channel->ch_close_partial = NULL;
2502
2503 /* any remaining messages are useless now */
2504 for (part = PART_SOCK; part <= PART_ERR; ++part)
2505 drop_messages(channel, part);
2461 } 2506 }
2462 2507
2463 channel->ch_nb_close_cb = NULL; 2508 channel->ch_nb_close_cb = NULL;
2464 } 2509 }
2465 2510
2965 */ 3010 */
2966 void 3011 void
2967 common_channel_read(typval_T *argvars, typval_T *rettv, int raw) 3012 common_channel_read(typval_T *argvars, typval_T *rettv, int raw)
2968 { 3013 {
2969 channel_T *channel; 3014 channel_T *channel;
2970 int part; 3015 int part = -1;
2971 jobopt_T opt; 3016 jobopt_T opt;
2972 int mode; 3017 int mode;
2973 int timeout; 3018 int timeout;
2974 int id = -1; 3019 int id = -1;
2975 typval_T *listtv = NULL; 3020 typval_T *listtv = NULL;
2981 clear_job_options(&opt); 3026 clear_job_options(&opt);
2982 if (get_job_options(&argvars[1], &opt, JO_TIMEOUT + JO_PART + JO_ID) 3027 if (get_job_options(&argvars[1], &opt, JO_TIMEOUT + JO_PART + JO_ID)
2983 == FAIL) 3028 == FAIL)
2984 goto theend; 3029 goto theend;
2985 3030
2986 channel = get_channel_arg(&argvars[0], TRUE); 3031 if (opt.jo_set & JO_PART)
3032 part = opt.jo_part;
3033 channel = get_channel_arg(&argvars[0], TRUE, TRUE, part);
2987 if (channel != NULL) 3034 if (channel != NULL)
2988 { 3035 {
2989 if (opt.jo_set & JO_PART) 3036 if (part < 0)
2990 part = opt.jo_part;
2991 else
2992 part = channel_part_read(channel); 3037 part = channel_part_read(channel);
2993 mode = channel_get_mode(channel, part); 3038 mode = channel_get_mode(channel, part);
2994 timeout = channel_get_timeout(channel, part); 3039 timeout = channel_get_timeout(channel, part);
2995 if (opt.jo_set & JO_TIMEOUT) 3040 if (opt.jo_set & JO_TIMEOUT)
2996 timeout = opt.jo_timeout; 3041 timeout = opt.jo_timeout;
3150 { 3195 {
3151 channel_T *channel; 3196 channel_T *channel;
3152 int part_send; 3197 int part_send;
3153 3198
3154 clear_job_options(opt); 3199 clear_job_options(opt);
3155 channel = get_channel_arg(&argvars[0], TRUE); 3200 channel = get_channel_arg(&argvars[0], TRUE, FALSE, 0);
3156 if (channel == NULL) 3201 if (channel == NULL)
3157 return NULL; 3202 return NULL;
3158 part_send = channel_part_send(channel); 3203 part_send = channel_part_send(channel);
3159 *part_read = channel_part_read(channel); 3204 *part_read = channel_part_read(channel);
3160 3205
3199 3244
3200 /* return an empty string by default */ 3245 /* return an empty string by default */
3201 rettv->v_type = VAR_STRING; 3246 rettv->v_type = VAR_STRING;
3202 rettv->vval.v_string = NULL; 3247 rettv->vval.v_string = NULL;
3203 3248
3204 channel = get_channel_arg(&argvars[0], TRUE); 3249 channel = get_channel_arg(&argvars[0], TRUE, FALSE, 0);
3205 if (channel == NULL) 3250 if (channel == NULL)
3206 return; 3251 return;
3207 part_send = channel_part_send(channel); 3252 part_send = channel_part_send(channel);
3208 3253
3209 ch_mode = channel_get_mode(channel, part_send); 3254 ch_mode = channel_get_mode(channel, part_send);
3431 } 3476 }
3432 3477
3433 return ret; 3478 return ret;
3434 } 3479 }
3435 # endif /* !WIN32 && HAVE_SELECT */ 3480 # endif /* !WIN32 && HAVE_SELECT */
3436
3437 /*
3438 * Return TRUE if "channel" has JSON or other typeahead.
3439 */
3440 static int
3441 channel_has_readahead(channel_T *channel, int part)
3442 {
3443 ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
3444
3445 if (ch_mode == MODE_JSON || ch_mode == MODE_JS)
3446 {
3447 jsonq_T *head = &channel->ch_part[part].ch_json_head;
3448 jsonq_T *item = head->jq_next;
3449
3450 return item != NULL;
3451 }
3452 return channel_peek(channel, part) != NULL;
3453 }
3454 3481
3455 /* 3482 /*
3456 * Execute queued up commands. 3483 * Execute queued up commands.
3457 * Invoked from the main loop when it's safe to execute received commands. 3484 * Invoked from the main loop when it's safe to execute received commands.
3458 * Return TRUE when something was done. 3485 * Return TRUE when something was done.
3966 } 3993 }
3967 3994
3968 /* 3995 /*
3969 * Get the channel from the argument. 3996 * Get the channel from the argument.
3970 * Returns NULL if the handle is invalid. 3997 * Returns NULL if the handle is invalid.
3998 * When "check_open" is TRUE check that the channel can be used.
3999 * When "reading" is TRUE "check_open" considers typeahead useful.
4000 * "part" is used to check typeahead, when -1 use the default part.
3971 */ 4001 */
3972 channel_T * 4002 channel_T *
3973 get_channel_arg(typval_T *tv, int check_open) 4003 get_channel_arg(typval_T *tv, int check_open, int reading, int part)
3974 { 4004 {
3975 channel_T *channel = NULL; 4005 channel_T *channel = NULL;
4006 int has_readahead = FALSE;
3976 4007
3977 if (tv->v_type == VAR_JOB) 4008 if (tv->v_type == VAR_JOB)
3978 { 4009 {
3979 if (tv->vval.v_job != NULL) 4010 if (tv->vval.v_job != NULL)
3980 channel = tv->vval.v_job->jv_channel; 4011 channel = tv->vval.v_job->jv_channel;
3986 else 4017 else
3987 { 4018 {
3988 EMSG2(_(e_invarg2), get_tv_string(tv)); 4019 EMSG2(_(e_invarg2), get_tv_string(tv));
3989 return NULL; 4020 return NULL;
3990 } 4021 }
3991 4022 if (channel != NULL && reading)
3992 if (check_open && (channel == NULL || !channel_is_open(channel))) 4023 has_readahead = channel_has_readahead(channel,
4024 part >= 0 ? part : channel_part_read(channel));
4025
4026 if (check_open && (channel == NULL || (!channel_is_open(channel)
4027 && !(reading && has_readahead))))
3993 { 4028 {
3994 EMSG(_("E906: not an open channel")); 4029 EMSG(_("E906: not an open channel"));
3995 return NULL; 4030 return NULL;
3996 } 4031 }
3997 return channel; 4032 return channel;