Skip to content

Commit

Permalink
Add API to prevent Fiber switch in select contexts
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Schröder <m.schroeder2007@gmail.com>
  • Loading branch information
trowski and kooldev committed Jun 14, 2021
1 parent 9871a62 commit fdc2274
Show file tree
Hide file tree
Showing 16 changed files with 237 additions and 156 deletions.
43 changes: 0 additions & 43 deletions Zend/tests/fibers/fiber-created-during-cleanup.phpt

This file was deleted.

24 changes: 0 additions & 24 deletions Zend/tests/fibers/fiber-created-in-destruct.phpt

This file was deleted.

35 changes: 0 additions & 35 deletions Zend/tests/fibers/fiber-in-destruct.phpt

This file was deleted.

29 changes: 0 additions & 29 deletions Zend/tests/fibers/fiber-throw-in-destruct.phpt

This file was deleted.

6 changes: 3 additions & 3 deletions Zend/tests/fibers/invocable-class.phpt
Expand Up @@ -20,8 +20,8 @@ $fiber = new Fiber($test);
$fiber->start();

?>
--EXPECT--
object(Test)#1 (0) {
--EXPECTF--
object(Test)#%d (0) {
}
object(Test)#1 (0) {
object(Test)#%d (0) {
}
30 changes: 30 additions & 0 deletions Zend/tests/fibers/no-switch-dtor-resume.phpt
@@ -0,0 +1,30 @@
--TEST--
Cannot resume fiber within destructor
--FILE--
<?php

$fiber = new Fiber(function () {
Fiber::suspend();
});
$fiber->start();

return new class ($fiber) {
private $fiber;

public function __construct(Fiber $fiber) {
$this->fiber = $fiber;
}

public function __destruct() {
$this->fiber->resume(1);
}
};

?>
--EXPECTF--
Fatal error: Uncaught FiberError: Cannot switch fibers in current execution context in %sno-switch-dtor-resume.php:%d
Stack trace:
#0 %sno-switch-dtor-resume.php(%d): Fiber->resume(1)
#1 %sno-switch-dtor-resume.php(%d): class@anonymous->__destruct()
#2 {main}
thrown in %sno-switch-dtor-resume.php on line %d
20 changes: 20 additions & 0 deletions Zend/tests/fibers/no-switch-dtor-start.phpt
@@ -0,0 +1,20 @@
--TEST--
Cannot start fiber within destructor
--FILE--
<?php

return new class () {
public function __destruct() {
$fiber = new Fiber(fn () => null);
$fiber->start();
}
};

?>
--EXPECTF--
Fatal error: Uncaught FiberError: Cannot switch fibers in current execution context in %sno-switch-dtor-start.php:%d
Stack trace:
#0 %sno-switch-dtor-start.php(%d): Fiber->start()
#1 %sno-switch-dtor-start.php(%d): class@anonymous->__destruct()
#2 {main}
thrown in %sno-switch-dtor-start.php on line %d
24 changes: 24 additions & 0 deletions Zend/tests/fibers/no-switch-dtor-suspend.phpt
@@ -0,0 +1,24 @@
--TEST--
Cannot suspend fiber within destructor
--FILE--
<?php

$fiber = new Fiber(function () {
$a = new class () {
public function __destruct() {
Fiber::suspend();
}
};
});

$fiber->start();

?>
--EXPECTF--
Fatal error: Uncaught FiberError: Cannot switch fibers in current execution context in %sno-switch-dtor-suspend.php:%d
Stack trace:
#0 %sno-switch-dtor-suspend.php(%d): Fiber::suspend()
#1 [internal function]: class@anonymous->__destruct()
#2 %sno-switch-dtor-suspend.php(%d): Fiber->start()
#3 {main}
thrown in %sno-switch-dtor-suspend.php on line %d
30 changes: 30 additions & 0 deletions Zend/tests/fibers/no-switch-dtor-throw.phpt
@@ -0,0 +1,30 @@
--TEST--
Cannot resume fiber within destructor
--FILE--
<?php

$fiber = new Fiber(function () {
Fiber::suspend();
});
$fiber->start();

return new class ($fiber) {
private $fiber;

public function __construct(Fiber $fiber) {
$this->fiber = $fiber;
}

public function __destruct() {
$this->fiber->throw(new Error());
}
};

?>
--EXPECTF--
Fatal error: Uncaught FiberError: Cannot switch fibers in current execution context in %sno-switch-dtor-throw.php:%d
Stack trace:
#0 %sno-switch-dtor-throw.php(%d): Fiber->throw(Object(Error))
#1 %sno-switch-dtor-throw.php(%d): class@anonymous->__destruct()
#2 {main}
thrown in %sno-switch-dtor-throw.php on line %d
31 changes: 31 additions & 0 deletions Zend/tests/fibers/no-switch-force-close-finally.phpt
@@ -0,0 +1,31 @@
--TEST--
Cannot start a new fiber in a finally block in a force-closed fiber
--FILE--
<?php

$fiber = new Fiber(function() {
try {
Fiber::suspend();
} finally {
echo "finally\n";

$fiber = new Fiber(function() {
echo "not executed\n";
});

$fiber->start();
}
});

$fiber->start();

?>
--EXPECTF--
finally

Fatal error: Uncaught FiberError: Cannot switch fibers in current execution context in %sno-switch-force-close-finally.php:%d
Stack trace:
#0 %sno-switch-force-close-finally.php(%d): Fiber->start()
#1 [internal function]: {closure}()
#2 {main}
thrown in %sno-switch-force-close-finally.php on line %d
35 changes: 35 additions & 0 deletions Zend/tests/fibers/no-switch-gc.phpt
@@ -0,0 +1,35 @@
--TEST--
Context switches are prevented during GC collect cycles
--FILE--
<?php

$fiber = new Fiber(function () {
call_user_func(function () {
$a = new class () {};

$b = new class () {
public function __destruct() {
Fiber::suspend();
}
};

$a->next = $b;
$b->next = $a;
});

gc_collect_cycles();
});

$fiber->start();

?>
--EXPECTF--
Fatal error: Uncaught FiberError: Cannot switch fibers in current execution context in %sno-switch-gc.php:%d
Stack trace:
#0 %sno-switch-gc.php(%d): Fiber::suspend()
#1 [internal function]: class@anonymous->__destruct()
#2 %sno-switch-gc.php(%d): gc_collect_cycles()
#3 [internal function]: {closure}()
#4 %sno-switch-gc.php(%d): Fiber->start()
#5 {main}
thrown in %sno-switch-gc.php on line %d
22 changes: 0 additions & 22 deletions Zend/tests/fibers/throw-from-destruct-with-fiber.phpt

This file was deleted.

0 comments on commit fdc2274

Please sign in to comment.