comparison src/channel.c @ 9085:d362e6df1deb v7.4.1827

commit https://github.com/vim/vim/commit/fb6ffc732e65dbc459c89247ff78134402f1a18b Author: Bram Moolenaar <Bram@vim.org> Date: Mon May 9 17:58:04 2016 +0200 patch 7.4.1827 Problem: No error when invoking a callback when it's not safe. Solution: Add an error message. Avoid the error when freeing a channel.
author Christian Brabandt <cb@256bit.org>
date Mon, 09 May 2016 18:00:06 +0200
parents 69bb7b230094
children d4606ae170aa
comparison
equal deleted inserted replaced
9084:8d3354777bf1 9085:d362e6df1deb
57 static void channel_read(channel_T *channel, int part, char *func); 57 static void channel_read(channel_T *channel, int part, char *func);
58 58
59 /* Whether a redraw is needed for appending a line to a buffer. */ 59 /* Whether a redraw is needed for appending a line to a buffer. */
60 static int channel_need_redraw = FALSE; 60 static int channel_need_redraw = FALSE;
61 61
62 /* Whether we are inside channel_parse_messages() or another situation where it
63 * is safe to invoke callbacks. */
64 static int safe_to_invoke_callback = 0;
62 65
63 #ifdef WIN32 66 #ifdef WIN32
64 static int 67 static int
65 fd_read(sock_T fd, char *buf, size_t len) 68 fd_read(sock_T fd, char *buf, size_t len)
66 { 69 {
401 static void 404 static void
402 channel_free(channel_T *channel) 405 channel_free(channel_T *channel)
403 { 406 {
404 if (!in_free_unref_items) 407 if (!in_free_unref_items)
405 { 408 {
406 channel_free_contents(channel); 409 if (safe_to_invoke_callback == 0)
407 channel_free_channel(channel); 410 {
411 channel->ch_to_be_freed = TRUE;
412 }
413 else
414 {
415 channel_free_contents(channel);
416 channel_free_channel(channel);
417 }
408 } 418 }
409 } 419 }
410 420
411 /* 421 /*
412 * Close a channel and free all its resources if there is no further action 422 * Close a channel and free all its resources if there is no further action
442 free_unused_channels_contents(int copyID, int mask) 452 free_unused_channels_contents(int copyID, int mask)
443 { 453 {
444 int did_free = FALSE; 454 int did_free = FALSE;
445 channel_T *ch; 455 channel_T *ch;
446 456
457 /* This is invoked from the garbage collector, which only runs at a safe
458 * point. */
459 ++safe_to_invoke_callback;
460
447 for (ch = first_channel; ch != NULL; ch = ch->ch_next) 461 for (ch = first_channel; ch != NULL; ch = ch->ch_next)
448 if (!channel_still_useful(ch) 462 if (!channel_still_useful(ch)
449 && (ch->ch_copyID & mask) != (copyID & mask)) 463 && (ch->ch_copyID & mask) != (copyID & mask))
450 { 464 {
451 /* Free the channel and ordinary items it contains, but don't 465 /* Free the channel and ordinary items it contains, but don't
452 * recurse into Lists, Dictionaries etc. */ 466 * recurse into Lists, Dictionaries etc. */
453 channel_free_contents(ch); 467 channel_free_contents(ch);
454 did_free = TRUE; 468 did_free = TRUE;
455 } 469 }
470
471 --safe_to_invoke_callback;
456 return did_free; 472 return did_free;
457 } 473 }
458 474
459 void 475 void
460 free_unused_channels(int copyID, int mask) 476 free_unused_channels(int copyID, int mask)
1447 invoke_callback(channel_T *channel, char_u *callback, partial_T *partial, 1463 invoke_callback(channel_T *channel, char_u *callback, partial_T *partial,
1448 typval_T *argv) 1464 typval_T *argv)
1449 { 1465 {
1450 typval_T rettv; 1466 typval_T rettv;
1451 int dummy; 1467 int dummy;
1468
1469 if (safe_to_invoke_callback == 0)
1470 EMSG("INTERNAL: Invoking callback when it is not safe");
1452 1471
1453 argv[0].v_type = VAR_CHANNEL; 1472 argv[0].v_type = VAR_CHANNEL;
1454 argv[0].vval.v_channel = channel; 1473 argv[0].vval.v_channel = channel;
1455 1474
1456 call_func(callback, (int)STRLEN(callback), 1475 call_func(callback, (int)STRLEN(callback),
3513 channel_T *channel = first_channel; 3532 channel_T *channel = first_channel;
3514 int ret = FALSE; 3533 int ret = FALSE;
3515 int r; 3534 int r;
3516 int part = PART_SOCK; 3535 int part = PART_SOCK;
3517 3536
3537 ++safe_to_invoke_callback;
3538
3518 /* Only do this message when another message was given, otherwise we get 3539 /* Only do this message when another message was given, otherwise we get
3519 * lots of them. */ 3540 * lots of them. */
3520 if (did_log_msg) 3541 if (did_log_msg)
3521 { 3542 {
3522 ch_log(NULL, "looking for messages on channels"); 3543 ch_log(NULL, "looking for messages on channels");
3527 if (channel->ch_to_be_closed) 3548 if (channel->ch_to_be_closed)
3528 { 3549 {
3529 channel->ch_to_be_closed = FALSE; 3550 channel->ch_to_be_closed = FALSE;
3530 channel_close_now(channel); 3551 channel_close_now(channel);
3531 /* channel may have been freed, start over */ 3552 /* channel may have been freed, start over */
3553 channel = first_channel;
3554 continue;
3555 }
3556 if (channel->ch_to_be_freed)
3557 {
3558 channel_free(channel);
3559 /* channel has been freed, start over */
3532 channel = first_channel; 3560 channel = first_channel;
3533 continue; 3561 continue;
3534 } 3562 }
3535 if (channel->ch_refcount == 0 && !channel_still_useful(channel)) 3563 if (channel->ch_refcount == 0 && !channel_still_useful(channel))
3536 { 3564 {
3569 if (channel_need_redraw) 3597 if (channel_need_redraw)
3570 { 3598 {
3571 channel_need_redraw = FALSE; 3599 channel_need_redraw = FALSE;
3572 redraw_after_callback(); 3600 redraw_after_callback();
3573 } 3601 }
3602
3603 --safe_to_invoke_callback;
3574 3604
3575 return ret; 3605 return ret;
3576 } 3606 }
3577 3607
3578 /* 3608 /*