Skip to content

Commit 7e11b4d

Browse files
authored
Improve memory allocation related code in zend_fibers (#7058)
- make_fcontext() never returns NULL. - Show syscall error info in exception just like zend_alloc does (we also used php_win32_error_*() in Zend). - MAP_ANON was marked as deprecated or compatibility macro on Linux, It would be better to use MAP_ANONYMOUS first. - Makes the code consistent with the code of other modules in the kernel. - adds some comments.
1 parent 2964262 commit 7e11b4d

File tree

1 file changed

+28
-14
lines changed

1 file changed

+28
-14
lines changed

Zend/zend_fibers.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,22 @@
3737
# include <unistd.h>
3838
# include <sys/mman.h>
3939
# 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
4056
#endif
4157

4258
#ifdef __SANITIZE_ADDRESS__
@@ -84,12 +100,6 @@ extern transfer_t jump_fcontext(fcontext_t to, void *vp);
84100
EG(bailout) = bailout; \
85101
} while (0)
86102

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-
93103
static size_t zend_fiber_get_page_size(void)
94104
{
95105
static size_t page_size = 0;
@@ -119,26 +129,36 @@ static bool zend_fiber_stack_allocate(zend_fiber_stack *stack, size_t size)
119129
pointer = VirtualAlloc(0, msize, MEM_COMMIT, PAGE_READWRITE);
120130

121131
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);
122136
return false;
123137
}
124138

125139
# if ZEND_FIBER_GUARD_PAGES
126140
DWORD protect;
127141

128142
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);
129147
VirtualFree(pointer, 0, MEM_RELEASE);
130148
return false;
131149
}
132150
# endif
133151
#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);
135153

136154
if (pointer == MAP_FAILED) {
155+
zend_throw_exception_ex(NULL, 0, "Fiber make context failed: mmap failed: %s (%d)", strerror(errno), errno);
137156
return false;
138157
}
139158

140159
# if ZEND_FIBER_GUARD_PAGES
141160
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);
142162
munmap(pointer, msize);
143163
return false;
144164
}
@@ -211,12 +231,7 @@ ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_co
211231
void *stack = (void *) ((uintptr_t) context->stack.pointer + context->stack.size);
212232

213233
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");
220235
context->function = coroutine;
221236
context->caller = NULL;
222237

@@ -479,7 +494,6 @@ ZEND_API void zend_fiber_start(zend_fiber *fiber, zval *params, uint32_t param_c
479494
fiber->fci.named_params = named_params;
480495

481496
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);
483497
RETURN_THROWS();
484498
}
485499

0 commit comments

Comments
 (0)