Skip to content

Commit 09838f1

Browse files
authored
zend_call_stack support proposal for solaris/illumos. (#12862)
1 parent 2ffd040 commit 09838f1

File tree

3 files changed

+138
-1
lines changed

3 files changed

+138
-1
lines changed

Zend/zend_call_stack.c

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
# include <sys/types.h>
3636
# endif
3737
#endif /* ZEND_WIN32 */
38-
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
38+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
39+
defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
40+
defined(__sun)
3941
# include <pthread.h>
4042
#endif
4143
#if defined(__FreeBSD__) || defined(__DragonFly__)
@@ -61,6 +63,12 @@ typedef int boolean_t;
6163
#ifdef __linux__
6264
#include <sys/syscall.h>
6365
#endif
66+
#ifdef __sun
67+
#define _STRUCTURED_PROC 1
68+
#include <sys/lwp.h>
69+
#include <sys/procfs.h>
70+
#include <libproc.h>
71+
#endif
6472

6573
#ifdef ZEND_CHECK_STACK_LIMIT
6674

@@ -650,6 +658,125 @@ static bool zend_call_stack_get_netbsd(zend_call_stack *stack)
650658
}
651659
#endif /* defined(__NetBSD__) */
652660

661+
#if defined(__sun)
662+
static bool zend_call_stack_get_solaris_pthread(zend_call_stack *stack)
663+
{
664+
pthread_attr_t attr;
665+
int error;
666+
void *addr;
667+
size_t max_size, guard_size;
668+
669+
error = pthread_attr_get_np(pthread_self(), &attr);
670+
if (error) {
671+
return false;
672+
}
673+
674+
error = pthread_attr_getstack(&attr, &addr, &max_size);
675+
if (error) {
676+
return false;
677+
}
678+
679+
error = pthread_attr_getguardsize(&attr, &guard_size);
680+
if (error) {
681+
return false;
682+
}
683+
684+
addr = (char *)addr + guard_size;
685+
max_size -= guard_size;
686+
687+
stack->base = (char *)addr + max_size;
688+
stack->max_size = max_size;
689+
690+
return true;
691+
}
692+
693+
static bool zend_call_stack_get_solaris_proc_maps(zend_call_stack *stack)
694+
{
695+
char buffer[4096];
696+
uintptr_t addr_on_stack = (uintptr_t)&buffer;
697+
bool found = false, r = false;
698+
struct ps_prochandle *proc;
699+
prmap_t *map, *orig;
700+
struct rlimit rlim;
701+
char path[PATH_MAX];
702+
size_t size;
703+
ssize_t len;
704+
pid_t pid;
705+
int error, fd;
706+
707+
pid = getpid();
708+
proc = Pgrab(pid, PGRAB_RDONLY, &error);
709+
if (!proc) {
710+
return false;
711+
}
712+
713+
size = (1 << 20);
714+
snprintf(path, sizeof(path), "/proc/%d/map", pid);
715+
716+
if ((fd = open(path, O_RDONLY)) == -1) {
717+
Prelease(proc, 0);
718+
return false;
719+
}
720+
721+
orig = malloc(size);
722+
if (!orig) {
723+
Prelease(proc, 0);
724+
close(fd);
725+
return false;
726+
}
727+
728+
while (size > 0 && (len = pread(fd, orig, size, 0)) == size) {
729+
prmap_t *tmp;
730+
size <<= 1;
731+
tmp = realloc(orig, size);
732+
if (!tmp) {
733+
goto end;
734+
}
735+
orig = tmp;
736+
}
737+
738+
for (map = orig; len > 0; ++map) {
739+
if ((uintptr_t)map->pr_vaddr <= addr_on_stack && (uintptr_t)map->pr_vaddr + map->pr_size >= addr_on_stack) {
740+
found = true;
741+
break;
742+
}
743+
len -= sizeof(*map);
744+
}
745+
746+
if (!found) {
747+
goto end;
748+
}
749+
750+
error = getrlimit(RLIMIT_STACK, &rlim);
751+
if (error || rlim.rlim_cur == RLIM_INFINITY) {
752+
goto end;
753+
}
754+
755+
stack->base = (void *)map->pr_vaddr + map->pr_size;
756+
stack->max_size = rlim.rlim_cur;
757+
r = true;
758+
759+
end:
760+
free(orig);
761+
Prelease(proc, 0);
762+
close(fd);
763+
return r;
764+
}
765+
766+
static bool zend_call_stack_get_solaris(zend_call_stack *stack)
767+
{
768+
if (_lwp_self() == 1) {
769+
return zend_call_stack_get_solaris_proc_maps(stack);
770+
}
771+
return zend_call_stack_get_solaris_pthread(stack);
772+
}
773+
#else
774+
static bool zend_call_stack_get_solaris(zend_call_stack *stack)
775+
{
776+
return false;
777+
}
778+
#endif /* defined(__sun) */
779+
653780
/** Get the stack information for the calling thread */
654781
ZEND_API bool zend_call_stack_get(zend_call_stack *stack)
655782
{
@@ -681,6 +808,10 @@ ZEND_API bool zend_call_stack_get(zend_call_stack *stack)
681808
return true;
682809
}
683810

811+
if (zend_call_stack_get_solaris(stack)) {
812+
return true;
813+
}
814+
684815
return false;
685816
}
686817

Zend/zend_call_stack.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ static inline size_t zend_call_stack_default_size(void)
9292
#ifdef __HAIKU__
9393
return 64 * 4096;
9494
#endif
95+
#ifdef __sun
96+
return 8 * 4096;
97+
#endif
9598

9699
return 2 * 1024 * 1024;
97100
}

configure.ac

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,9 @@ PHP_CHECK_FUNC_LIB(nanosleep, rt)
656656
dnl Haiku does not have network api in libc.
657657
PHP_CHECK_FUNC_LIB(setsockopt, network)
658658

659+
dnl Solaris/Illumos for process mapping.
660+
PHP_CHECK_FUNC_LIB(Pgrab, proc)
661+
659662
dnl Check for getaddrinfo, should be a better way, but... Also check for working
660663
dnl getaddrinfo.
661664
AC_CACHE_CHECK([for getaddrinfo], ac_cv_func_getaddrinfo,

0 commit comments

Comments
 (0)