@@ -13,7 +13,12 @@ function timeout(PromiseInterface $promise, $time, LoopInterface $loop)
13
13
// thus leaving responsibility to the input promise.
14
14
$ canceller = null ;
15
15
if ($ promise instanceof CancellablePromiseInterface) {
16
- $ canceller = array ($ promise , 'cancel ' );
16
+ // pass promise by reference to clean reference after cancellation handler
17
+ // has been invoked once in order to avoid garbage references in call stack.
18
+ $ canceller = function () use (&$ promise ) {
19
+ $ promise ->cancel ();
20
+ $ promise = null ;
21
+ };
17
22
}
18
23
19
24
return new Promise (function ($ resolve , $ reject ) use ($ loop , $ time , $ promise ) {
@@ -38,12 +43,15 @@ function timeout(PromiseInterface $promise, $time, LoopInterface $loop)
38
43
}
39
44
40
45
// start timeout timer which will cancel the input promise
41
- $ timer = $ loop ->addTimer ($ time , function () use ($ time , $ promise , $ reject ) {
46
+ $ timer = $ loop ->addTimer ($ time , function () use ($ time , & $ promise , $ reject ) {
42
47
$ reject (new TimeoutException ($ time , 'Timed out after ' . $ time . ' seconds ' ));
43
48
49
+ // try to invoke cancellation handler of input promise and then clean
50
+ // reference in order to avoid garbage references in call stack.
44
51
if ($ promise instanceof CancellablePromiseInterface) {
45
52
$ promise ->cancel ();
46
53
}
54
+ $ promise = null ;
47
55
});
48
56
}, $ canceller );
49
57
}
@@ -55,11 +63,12 @@ function resolve($time, LoopInterface $loop)
55
63
$ timer = $ loop ->addTimer ($ time , function () use ($ time , $ resolve ) {
56
64
$ resolve ($ time );
57
65
});
58
- }, function ($ resolve , $ reject , $ notify ) use (&$ timer , $ loop ) {
59
- // cancelling this promise will cancel the timer and reject
66
+ }, function () use (&$ timer , $ loop ) {
67
+ // cancelling this promise will cancel the timer, clean the reference
68
+ // in order to avoid garbage references in call stack and then reject.
60
69
$ loop ->cancelTimer ($ timer );
70
+ $ timer = null ;
61
71
62
- $ resolve = $ reject = $ notify = $ timer = $ loop = null ;
63
72
throw new \RuntimeException ('Timer cancelled ' );
64
73
});
65
74
}
0 commit comments