Skip to content
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

zend call stack fix freebsd code path. #11766

Merged
merged 2 commits into from Jul 23, 2023

Conversation

devnexen
Copy link
Member

The typo in HAVE_PTHREAD_ATTR_GET_STACK (might be due to pthread_attr_get_np being different from Linux's pthread_getattr_np) led to this code path never get called on FreeBSD. Anyway, like Linux the first condition alone is enough, pthread_attr_getstack being present
even in the 9.x release's serie.

@petk
Copy link
Member

petk commented Jul 22, 2023

Ah, now I understand the comment in #11762... It's a typo and the HAVE_PTHREAD_ATTR_GET_STACK is used in the code instead of the HAVE_PTHREAD_ATTR_GETSTACK. I have no idea how I've missed that. I've missed that pthread_attr_getstack is actually used. 😀

Then why not just changing the constant name to HAVE_PTHREAD_ATTR_GETSTACK? I think it would be more correct since theoretically it might not be defined on some system. It's not part of any standard or docs and it doesn't hurt to be as thorough as possible.

Edit: This changes the execution of the code then. Now, this code is not executed on any platform... 🤔

@devnexen
Copy link
Member Author

Not sure I get what you mean this part of the code is exclusive to freebsd.

@devnexen
Copy link
Member Author

Anyway cc @arnaud-lb since he s the author of the FreeBSD's implementation :)

@petk
Copy link
Member

petk commented Jul 22, 2023

Yes, but the HAVE_PTHREAD_ATTR_GET_STACK is not defined anywhere so only that part of the code is not executed. Since the pthread_attr_getstack is already called in zend_call_stack_get_linux_pthread without the check it probably is fine to do that, yes.

I've changed my PR now so only one change is done. Then can you remove also pthread_attr_getstack check in Zend.m4?

@devnexen
Copy link
Member Author

ah sure I did not see your PR change.

Copy link
Member

@arnaud-lb arnaud-lb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, thank you!

You also add -lpthread, is this on purpose? Should we avoid linking to pthread when it's not necessary? (in non-ZTS builds) Can it affect SAPIs in any way?

Zend/Zend.m4 Outdated
@@ -212,6 +212,7 @@ AX_CHECK_COMPILE_FLAG([-Wlogical-op], CFLAGS="-Wlogical-op $CFLAGS", , [-Werror]
AX_CHECK_COMPILE_FLAG([-Wformat-truncation], CFLAGS="-Wformat-truncation $CFLAGS", , [-Werror])
AX_CHECK_COMPILE_FLAG([-Wstrict-prototypes], CFLAGS="-Wstrict-prototypes $CFLAGS", , [-Werror])
AX_CHECK_COMPILE_FLAG([-fno-common], CFLAGS="-fno-common $CFLAGS", , [-Werror])
AX_CHECK_COMPILE_FLAG([-pthread], CFLAGS="-pthread $CFLAGS", , [-Werror])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It this change on purpose?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh now I remember why I checked for the availability of both pthread_attr_get_np and pthread_attr_getstack: The libc provides a stub for pthread_attr_get_np, but not for pthread_attr_getstack, when not linking with pthread.

There are stubs for pthread_attr_getstackaddr and pthread_attr_getstacksize though.

We should check for the availability of pthread_attr_getstack, or switch to pthread_attr_getstackaddr and pthread_attr_getstacksize. After that we can avoid explicitly linking to pthread in non-ZTS builds.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since pthread_attr_getstackaddr and pthread_attr_getstacksize are deprecated, we should go for checking the availability of pthread_attr_getstack and use it in zend_call_stack_get_freebsd_pthread.

We will compile the stub version of zend_call_stack_get_freebsd_pthread when not linking with pthread, which is fine.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact the deprecation warning occured on Linux should I change it too there ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that you have already done it :) It's better if we can avoid depending on deprecated functions.

@devnexen devnexen force-pushed the zend_call_stack_fbsd_build_fix branch from bb40c12 to 090ed09 Compare July 22, 2023 19:37
…_get_np being different from Linux's pthread_getattr_np) led to this code path never get called on FreeBSD.
Comment on lines 278 to 284
error = pthread_attr_getguardsize(&attr, &guard_size);
if (error) {
return false;
}

addr = (char *)addr + guard_size;
max_size -= guard_size;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From reading the code and testing, addr and size reported by pthread_attr_getstack() appear to reflect the usable stack, and they are not affected by the guard size. Based on that, we should not adjust addr and max_size here. But you may have a different experience. Is this required on some FreeBSD version? On Linux this is required in Glibc < 2.8.

In 13.1, the stack is allocated here: https://github.com/freebsd/freebsd-src/blob/releng/13.1/lib/libthr/thread/thr_stack.c#L276. As we can see, the map size is computed from stacksize + guardsize. stacksize and guardsize come directly from the pthread_attr (they are just rounded to the nearest page multiple). pthread_attr_setstack() does not adjust addr and size with the guardsize, and pthread_attr_setguardsize() does not adjust addr and size either. The get versions of these functions also report these values directly.

I verified with this program: https://gist.github.com/arnaud-lb/a53eb410b7c26b38fd01eac2cee0467e. The program starts 3 threads: Thread 1 with the default attrs, thread 2 with the guard size set to 1MiB, and thread 3 with the guard size set to 16MiB (larger than the stack size). Each thread then recurses until it reaches the address reported by pthread_attr_getstack(). If this address is the actual base of the stack, this should not crash. If this address is in or bellow the guard pages, this should crash. During my tests, this did not crash.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The FreeBSD manpage does not help a lot, but it mentions that these functions conform to POSIX.1. The posix spec about pthread_attr_getstack() says this:

All pages within the stack described by stackaddr and stacksize shall be both readable and writable by the thread.

There could still be a bug or a discrepancy in FreeBSD's implementation, so I wouldn't trust the spec alone, but this matches what I was seeing above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No my mistake even in old releases the guard size is already.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No my mistake even in old releases the guard size is already.

Copy link
Member

@arnaud-lb arnaud-lb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@devnexen devnexen merged commit 6602dde into php:master Jul 23, 2023
12 checks passed
jorgsowa pushed a commit to jorgsowa/php-src that referenced this pull request Jul 26, 2023
The typo in HAVE_PTHREAD_ATTR_GET_STACK (might be due to pthread_attr_get_np being different from Linux's pthread_getattr_np) led to this code path never get called on FreeBSD.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants