Mercurial > vim
comparison src/channel.c @ 8074:dc32c8026899 v7.4.1331
commit https://github.com/vim/vim/commit/d46ae142aa9452e99576b5e923de974704e3c896
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Feb 16 13:33:52 2016 +0100
patch 7.4.1331
Problem: Crash when closing the channel in a callback. (Christian J.
Robinson)
Solution: Take the callback out of the list before invoking it.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Tue, 16 Feb 2016 13:45:04 +0100 |
parents | 38887bf423ba |
children | b6cb94ad97a4 |
comparison
equal
deleted
inserted
replaced
8073:42db5fe07958 | 8074:dc32c8026899 |
---|---|
886 vim_free(reader.js_buf); | 886 vim_free(reader.js_buf); |
887 return ret; | 887 return ret; |
888 } | 888 } |
889 | 889 |
890 /* | 890 /* |
891 * Remove "node" from the queue that it is in and free it. | 891 * Remove "node" from the queue that it is in. Does not free it. |
892 * Also frees the contained callback name. | |
893 */ | 892 */ |
894 static void | 893 static void |
895 remove_cb_node(cbq_T *head, cbq_T *node) | 894 remove_cb_node(cbq_T *head, cbq_T *node) |
896 { | 895 { |
897 if (node->cq_prev == NULL) | 896 if (node->cq_prev == NULL) |
900 node->cq_prev->cq_next = node->cq_next; | 899 node->cq_prev->cq_next = node->cq_next; |
901 if (node->cq_next == NULL) | 900 if (node->cq_next == NULL) |
902 head->cq_prev = node->cq_prev; | 901 head->cq_prev = node->cq_prev; |
903 else | 902 else |
904 node->cq_next->cq_prev = node->cq_prev; | 903 node->cq_next->cq_prev = node->cq_prev; |
905 vim_free(node->cq_callback); | |
906 vim_free(node); | |
907 } | 904 } |
908 | 905 |
909 /* | 906 /* |
910 * Remove "node" from the queue that it is in and free it. | 907 * Remove "node" from the queue that it is in and free it. |
911 * Caller should have freed or used node->jq_value. | 908 * Caller should have freed or used node->jq_value. |
1142 while (item != NULL) | 1139 while (item != NULL) |
1143 { | 1140 { |
1144 if (item->cq_seq_nr == seq_nr) | 1141 if (item->cq_seq_nr == seq_nr) |
1145 { | 1142 { |
1146 ch_log(channel, "Invoking one-time callback\n"); | 1143 ch_log(channel, "Invoking one-time callback\n"); |
1144 /* Remove the item from the list first, if the callback | |
1145 * invokes ch_close() the list will be cleared. */ | |
1146 remove_cb_node(head, item); | |
1147 invoke_callback(channel, item->cq_callback, argv); | 1147 invoke_callback(channel, item->cq_callback, argv); |
1148 remove_cb_node(head, item); | 1148 vim_free(item->cq_callback); |
1149 vim_free(item); | |
1149 done = TRUE; | 1150 done = TRUE; |
1150 break; | 1151 break; |
1151 } | 1152 } |
1152 item = item->cq_next; | 1153 item = item->cq_next; |
1153 } | 1154 } |
1327 | 1328 |
1328 while (channel_peek(channel) != NULL) | 1329 while (channel_peek(channel) != NULL) |
1329 vim_free(channel_get(channel)); | 1330 vim_free(channel_get(channel)); |
1330 | 1331 |
1331 while (cb_head->cq_next != NULL) | 1332 while (cb_head->cq_next != NULL) |
1332 remove_cb_node(cb_head, cb_head->cq_next); | 1333 { |
1334 cbq_T *node = cb_head->cq_next; | |
1335 | |
1336 remove_cb_node(cb_head, node); | |
1337 vim_free(node->cq_callback); | |
1338 vim_free(node); | |
1339 } | |
1333 | 1340 |
1334 while (json_head->jq_next != NULL) | 1341 while (json_head->jq_next != NULL) |
1335 { | 1342 { |
1336 free_tv(json_head->jq_next->jq_value); | 1343 free_tv(json_head->jq_next->jq_value); |
1337 remove_json_node(json_head, json_head->jq_next); | 1344 remove_json_node(json_head, json_head->jq_next); |