Mercurial > vim
comparison src/ex_cmds2.c @ 10066:dc1610dc910f v7.4.2304
commit https://github.com/vim/vim/commit/417ccd7138d4d230d328de8b0d3892dd82ff1bee
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Sep 1 21:26:20 2016 +0200
patch 7.4.2304
Problem: In a timer callback the timer itself can't be found or stopped.
(Thinca)
Solution: Do not remove the timer from the list, remember whether it was
freed.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 01 Sep 2016 21:30:05 +0200 |
parents | 4aead6a9b7a9 |
children | 32bd4001e398 |
comparison
equal
deleted
inserted
replaced
10065:e22dde82d394 | 10066:dc1610dc910f |
---|---|
1088 | 1088 |
1089 # if defined(FEAT_TIMERS) || defined(PROTO) | 1089 # if defined(FEAT_TIMERS) || defined(PROTO) |
1090 static timer_T *first_timer = NULL; | 1090 static timer_T *first_timer = NULL; |
1091 static int last_timer_id = 0; | 1091 static int last_timer_id = 0; |
1092 | 1092 |
1093 static timer_T *current_timer = NULL; | |
1094 static int free_current_timer = FALSE; | |
1095 | |
1093 /* | 1096 /* |
1094 * Insert a timer in the list of timers. | 1097 * Insert a timer in the list of timers. |
1095 */ | 1098 */ |
1096 static void | 1099 static void |
1097 insert_timer(timer_T *timer) | 1100 insert_timer(timer_T *timer) |
1119 } | 1122 } |
1120 | 1123 |
1121 static void | 1124 static void |
1122 free_timer(timer_T *timer) | 1125 free_timer(timer_T *timer) |
1123 { | 1126 { |
1124 free_callback(timer->tr_callback, timer->tr_partial); | 1127 if (timer == current_timer) |
1125 vim_free(timer); | 1128 free_current_timer = TRUE; |
1129 else | |
1130 { | |
1131 free_callback(timer->tr_callback, timer->tr_partial); | |
1132 vim_free(timer); | |
1133 } | |
1126 } | 1134 } |
1127 | 1135 |
1128 /* | 1136 /* |
1129 * Create a timer and return it. NULL if out of memory. | 1137 * Create a timer and return it. NULL if out of memory. |
1130 * Caller should set the callback. | 1138 * Caller should set the callback. |
1198 this_due = (timer->tr_due.tv_sec - now.tv_sec) * 1000 | 1206 this_due = (timer->tr_due.tv_sec - now.tv_sec) * 1000 |
1199 + (timer->tr_due.tv_usec - now.tv_usec) / 1000; | 1207 + (timer->tr_due.tv_usec - now.tv_usec) / 1000; |
1200 # endif | 1208 # endif |
1201 if (this_due <= 1) | 1209 if (this_due <= 1) |
1202 { | 1210 { |
1203 remove_timer(timer); | 1211 current_timer = timer; |
1212 free_current_timer = FALSE; | |
1204 timer_callback(timer); | 1213 timer_callback(timer); |
1214 current_timer = NULL; | |
1215 | |
1205 did_one = TRUE; | 1216 did_one = TRUE; |
1206 if (timer->tr_repeat != 0) | 1217 if (timer->tr_repeat != 0 && !free_current_timer) |
1207 { | 1218 { |
1208 profile_setlimit(timer->tr_interval, &timer->tr_due); | 1219 profile_setlimit(timer->tr_interval, &timer->tr_due); |
1209 if (timer->tr_repeat > 0) | 1220 if (timer->tr_repeat > 0) |
1210 --timer->tr_repeat; | 1221 --timer->tr_repeat; |
1211 insert_timer(timer); | |
1212 } | 1222 } |
1213 else | 1223 else |
1224 { | |
1214 free_timer(timer); | 1225 free_timer(timer); |
1226 remove_timer(timer); | |
1227 } | |
1215 /* the callback may do anything, start all over */ | 1228 /* the callback may do anything, start all over */ |
1216 break; | 1229 break; |
1217 } | 1230 } |
1218 if (next_due == -1 || next_due > this_due) | 1231 if (next_due == -1 || next_due > this_due) |
1219 next_due = this_due; | 1232 next_due = this_due; |