|
37 | 37 | # include <unistd.h>
|
38 | 38 | # include <sys/mman.h>
|
39 | 39 | # include <limits.h>
|
| 40 | + |
| 41 | +# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) |
| 42 | +# define MAP_ANONYMOUS MAP_ANON |
| 43 | +# endif |
| 44 | + |
| 45 | +/* FreeBSD require a first (i.e. addr) argument of mmap(2) is not NULL |
| 46 | + * if MAP_STACK is passed. |
| 47 | + * http://www.FreeBSD.org/cgi/query-pr.cgi?pr=158755 */ |
| 48 | +# if !defined(MAP_STACK) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) |
| 49 | +# undef MAP_STACK |
| 50 | +# define MAP_STACK 0 |
| 51 | +# endif |
| 52 | + |
| 53 | +# ifndef MAP_FAILED |
| 54 | +# define MAP_FAILED ((void * ) -1) |
| 55 | +# endif |
40 | 56 | #endif
|
41 | 57 |
|
42 | 58 | #ifdef __SANITIZE_ADDRESS__
|
@@ -84,12 +100,6 @@ extern transfer_t jump_fcontext(fcontext_t to, void *vp);
|
84 | 100 | EG(bailout) = bailout; \
|
85 | 101 | } while (0)
|
86 | 102 |
|
87 |
| -#if defined(MAP_STACK) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) |
88 |
| -# define ZEND_FIBER_STACK_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_STACK) |
89 |
| -#else |
90 |
| -# define ZEND_FIBER_STACK_FLAGS (MAP_PRIVATE | MAP_ANON) |
91 |
| -#endif |
92 |
| - |
93 | 103 | static size_t zend_fiber_get_page_size(void)
|
94 | 104 | {
|
95 | 105 | static size_t page_size = 0;
|
@@ -119,26 +129,36 @@ static bool zend_fiber_stack_allocate(zend_fiber_stack *stack, size_t size)
|
119 | 129 | pointer = VirtualAlloc(0, msize, MEM_COMMIT, PAGE_READWRITE);
|
120 | 130 |
|
121 | 131 | if (!pointer) {
|
| 132 | + DWORD err = GetLastError(); |
| 133 | + char *errmsg = php_win32_error_to_msg(err); |
| 134 | + zend_throw_exception_ex(NULL, 0, "Fiber make context failed: VirtualAlloc failed: [0x%08lx] %s", err, errmsg[0] ? errmsg : "Unknown"); |
| 135 | + php_win32_error_msg_free(errmsg); |
122 | 136 | return false;
|
123 | 137 | }
|
124 | 138 |
|
125 | 139 | # if ZEND_FIBER_GUARD_PAGES
|
126 | 140 | DWORD protect;
|
127 | 141 |
|
128 | 142 | if (!VirtualProtect(pointer, ZEND_FIBER_GUARD_PAGES * page_size, PAGE_READWRITE | PAGE_GUARD, &protect)) {
|
| 143 | + DWORD err = GetLastError(); |
| 144 | + char *errmsg = php_win32_error_to_msg(err); |
| 145 | + zend_throw_exception_ex(NULL, 0, "Fiber protect stack failed: VirtualProtect failed: [0x%08lx] %s", err, errmsg[0] ? errmsg : "Unknown"); |
| 146 | + php_win32_error_msg_free(errmsg); |
129 | 147 | VirtualFree(pointer, 0, MEM_RELEASE);
|
130 | 148 | return false;
|
131 | 149 | }
|
132 | 150 | # endif
|
133 | 151 | #else
|
134 |
| - pointer = mmap(NULL, msize, PROT_READ | PROT_WRITE, ZEND_FIBER_STACK_FLAGS, -1, 0); |
| 152 | + pointer = mmap(NULL, msize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); |
135 | 153 |
|
136 | 154 | if (pointer == MAP_FAILED) {
|
| 155 | + zend_throw_exception_ex(NULL, 0, "Fiber make context failed: mmap failed: %s (%d)", strerror(errno), errno); |
137 | 156 | return false;
|
138 | 157 | }
|
139 | 158 |
|
140 | 159 | # if ZEND_FIBER_GUARD_PAGES
|
141 | 160 | if (mprotect(pointer, ZEND_FIBER_GUARD_PAGES * page_size, PROT_NONE) < 0) {
|
| 161 | + zend_throw_exception_ex(NULL, 0, "Fiber protect stack failed: mmap failed: %s (%d)", strerror(errno), errno); |
142 | 162 | munmap(pointer, msize);
|
143 | 163 | return false;
|
144 | 164 | }
|
@@ -211,12 +231,7 @@ ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_co
|
211 | 231 | void *stack = (void *) ((uintptr_t) context->stack.pointer + context->stack.size);
|
212 | 232 |
|
213 | 233 | context->self = make_fcontext(stack, context->stack.size, zend_fiber_trampoline);
|
214 |
| - |
215 |
| - if (UNEXPECTED(!context->self)) { |
216 |
| - zend_fiber_stack_free(&context->stack); |
217 |
| - return false; |
218 |
| - } |
219 |
| - |
| 234 | + ZEND_ASSERT(context->self != NULL && "make_fcontext() never returns NULL"); |
220 | 235 | context->function = coroutine;
|
221 | 236 | context->caller = NULL;
|
222 | 237 |
|
@@ -479,7 +494,6 @@ ZEND_API void zend_fiber_start(zend_fiber *fiber, zval *params, uint32_t param_c
|
479 | 494 | fiber->fci.named_params = named_params;
|
480 | 495 |
|
481 | 496 | if (!zend_fiber_init_context(&fiber->context, zend_fiber_execute, EG(fiber_stack_size))) {
|
482 |
| - zend_throw_exception(NULL, "Could not create fiber context", 0); |
483 | 497 | RETURN_THROWS();
|
484 | 498 | }
|
485 | 499 |
|
|
0 commit comments