Skip to content

zend_call_stack support proposal for solaris/illumos. #12862

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 132 additions & 1 deletion Zend/zend_call_stack.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
# include <sys/types.h>
# endif
#endif /* ZEND_WIN32 */
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
defined(__sun)
# include <pthread.h>
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__)
Expand All @@ -61,6 +63,12 @@ typedef int boolean_t;
#ifdef __linux__
#include <sys/syscall.h>
#endif
#ifdef __sun
#define _STRUCTURED_PROC 1
#include <sys/lwp.h>
#include <sys/procfs.h>
#include <libproc.h>
#endif

#ifdef ZEND_CHECK_STACK_LIMIT

Expand Down Expand Up @@ -650,6 +658,125 @@ static bool zend_call_stack_get_netbsd(zend_call_stack *stack)
}
#endif /* defined(__NetBSD__) */

#if defined(__sun)
static bool zend_call_stack_get_solaris_pthread(zend_call_stack *stack)
{
pthread_attr_t attr;
int error;
void *addr;
size_t max_size, guard_size;

error = pthread_attr_get_np(pthread_self(), &attr);
if (error) {
return false;
}

error = pthread_attr_getstack(&attr, &addr, &max_size);
if (error) {
return false;
}

error = pthread_attr_getguardsize(&attr, &guard_size);
if (error) {
return false;
}

addr = (char *)addr + guard_size;
max_size -= guard_size;

stack->base = (char *)addr + max_size;
stack->max_size = max_size;

return true;
}

static bool zend_call_stack_get_solaris_proc_maps(zend_call_stack *stack)
{
char buffer[4096];
uintptr_t addr_on_stack = (uintptr_t)&buffer;
bool found = false, r = false;
struct ps_prochandle *proc;
prmap_t *map, *orig;
struct rlimit rlim;
char path[PATH_MAX];
size_t size;
ssize_t len;
pid_t pid;
int error, fd;

pid = getpid();
proc = Pgrab(pid, PGRAB_RDONLY, &error);
if (!proc) {
return false;
}

size = (1 << 20);
snprintf(path, sizeof(path), "/proc/%d/map", pid);

if ((fd = open(path, O_RDONLY)) == -1) {
Prelease(proc, 0);
return false;
}

orig = malloc(size);
if (!orig) {
Prelease(proc, 0);
close(fd);
return false;
}

while (size > 0 && (len = pread(fd, orig, size, 0)) == size) {
prmap_t *tmp;
size <<= 1;
tmp = realloc(orig, size);
if (!tmp) {
goto end;
}
orig = tmp;
}

for (map = orig; len > 0; ++map) {
if ((uintptr_t)map->pr_vaddr <= addr_on_stack && (uintptr_t)map->pr_vaddr + map->pr_size >= addr_on_stack) {
found = true;
break;
}
len -= sizeof(*map);
}

if (!found) {
goto end;
}

error = getrlimit(RLIMIT_STACK, &rlim);
if (error || rlim.rlim_cur == RLIM_INFINITY) {
goto end;
}

stack->base = (void *)map->pr_vaddr + map->pr_size;
stack->max_size = rlim.rlim_cur;
r = true;

end:
free(orig);
Prelease(proc, 0);
close(fd);
return r;
}

static bool zend_call_stack_get_solaris(zend_call_stack *stack)
{
if (_lwp_self() == 1) {
return zend_call_stack_get_solaris_proc_maps(stack);
}
return zend_call_stack_get_solaris_pthread(stack);
}
#else
static bool zend_call_stack_get_solaris(zend_call_stack *stack)
{
return false;
}
#endif /* defined(__sun) */

/** Get the stack information for the calling thread */
ZEND_API bool zend_call_stack_get(zend_call_stack *stack)
{
Expand Down Expand Up @@ -681,6 +808,10 @@ ZEND_API bool zend_call_stack_get(zend_call_stack *stack)
return true;
}

if (zend_call_stack_get_solaris(stack)) {
return true;
}

return false;
}

Expand Down
3 changes: 3 additions & 0 deletions Zend/zend_call_stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ static inline size_t zend_call_stack_default_size(void)
#ifdef __HAIKU__
return 64 * 4096;
#endif
#ifdef __sun
return 8 * 4096;
#endif

return 2 * 1024 * 1024;
}
Expand Down
3 changes: 3 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,9 @@ PHP_CHECK_FUNC_LIB(nanosleep, rt)
dnl Haiku does not have network api in libc.
PHP_CHECK_FUNC_LIB(setsockopt, network)

dnl Solaris/Illumos for process mapping.
PHP_CHECK_FUNC_LIB(Pgrab, proc)

dnl Check for getaddrinfo, should be a better way, but... Also check for working
dnl getaddrinfo.
AC_CACHE_CHECK([for getaddrinfo], ac_cv_func_getaddrinfo,
Expand Down