dunglas / frankenphp

šŸ§Ÿ The modern PHP app server
https://frankenphp.dev
MIT License
6.81k stars 233 forks source link

Compilation errors due to pthread stuff #1047

Open rwv37 opened 3 weeks ago

rwv37 commented 3 weeks ago

What happened?

Building via xcaddy, I'm getting various compilation errors like this (by which I mean the same sort of thing for pthread_detach, pthread_join, etc.):

frankenphp.c:811:9: error: call to undeclared function 'pthread_create'; ISO C99 and later do not support implicit function declarations [-Werror,-Wimplicit-function-declaration]

I know very little about pthreads, but I think I've sussed out the issue (or at least an issue). Frankenphp.c has the following:

#if defined(__linux__)
#include <sys/prctl.h>
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
#include <pthread_np.h>
#endif

I am compiling on FreeBSD. These functions (like pthread_create) are defined in pthread.h, not in pthread_np.h.

To be clear, I don't mean to imply that #include <pthread_np.h> should be replaced by #include <pthread.h>. I have not looked closely enough to figure out whether or not both are needed, and like I said I know very little about pthreads. All I'm saying is that it seems very likely to me that #include <pthread.h> is needed.

Thank you!

Build Type

Custom (tell us more in the description)

Worker Mode

No

Operating System

Other (tell us more in the description)

CPU Architecture

x86_64

PHP configuration

(seems irrelevant? if you really want it, let me know)

Relevant log output

frankenphp.c:811:9: error: call to undeclared function 'pthread_create'; ISO C99 and later do not support implicit function declarations [-Werror,-Wimplicit-function-declaration]
dunglas commented 3 weeks ago

Hi,

I currently never tried to compile on FreeBSD, so there might be many issues like that.

I would likely merge patch fixing them!

rwv37 commented 3 weeks ago

OK. I'm a bit occupied, so I'm afraid I don't have much time to dedicate to this, but I figured I'd at least try just adding in the #include and seeing what happened:

First, I got other compilation errors saying that brotli/decode.h couldn't be found. I don't think I had even heard of brotli before looking at the sample Frankenphp xcaddy build command, so after getting this error, I looked it up and found it's an archiver or compressor or something. I therefore thought it was probably optional despite being in that sample command (right?), so rather than worry about compiling it, I removed it from the command and tried again.

Everything compiled fine. Caddy started up fine, and worked with all my existing configuration (which has several different sites using several different things, e.g. proxies and file servers, but no PHP).

I then made a Hello World-ish PHP site (just an index.php alone in a directory), and put the following in my Caddyfile (the import denyExternal is just a little thing I've been successfully using for a long time to deny requests from outside the local network):

https://blah.local {
   import denyExternal

   root * /blah/bobtmp
   php_server
}

After restarting Caddy, all the preexisting stuff still worked fine, but the new PHP site didn't. When I tried to go to it, the browser hung for a while on the request, and eventually just silently gave no result.

I then remembered having seen a frankenphp setting in the sample docs, so I went back and added that in:

{
   {
      frankenphp {
         worker /blah/bobtmp/index.php 8
      }
   }
}

Restarted Caddy, which then went into a tight infinite loop, putting the following message out once and then the next message out very very rapidly until I force-killed the process. First message (once):

{"level":"warn","ts":1727203762.6992579,"msg":"ZTS is not enabled, only 1 thread will be available, recompile PHP using the \"--enable-zts\" configuration option or performance will be degraded"}

Next message (tight loop):

{"level":"error","ts":1727203603.29097,"msg":"unexpected termination, restarting","worker":"/blah/bobtmp","exit_status":255}

I figured maybe the ZTS thing from the first message might have something to do with the "unexpected termination" thing from the tight loop message, so I changed the number of worker threads to one, and restarted. The same thing happened (i.e. both the ZTS message once and the "unexpected termination" message in a tight loop).

I'm sorry to say, again, that I don't have much time to dedicate to this. However, if you see something obvious that I'm doing incorrectly, or could try in some other way, I'd love to hear it.

rwv37 commented 3 weeks ago

Oh, and it's been years since I've really used PHP, so while it doesn't seem likely to me that this is the cause, here's the index.php just in case:

<html><head><title>Sickos</title></head><body>
<p>yesssssssssssss</p>
<p><i>yessssssssssssssssssssssss</i></p>
<p><i><b><?php echo "yessssssssssssssssssssssssssssssssssssssss"; ?></i></b></p>
</html>

.... aaaaaaaaaaaaand, now I'm extremely embarrassed by <i><b></i></b> šŸ˜›

... oh no, and no </body> too šŸ˜ž

rwv37 commented 3 weeks ago

Without seriously expecting it to help, I fixed the little errors in index.php, removed the frankenphp directive from Caddyfile, and tried again. It in fact did not help, but I got a little more information from it:

First, when I said this (regarding the first time when I tried without the frankenphp directive:

When I tried to go to it, the browser hung for a while on the request, and eventually just silently gave no result.

I don't think that's correct. This time, the browser hung indefinitely, and I had to force-kill the Caddy process. I'm guessing I had done so the first time too, but had forgotten that by the time I typed up my previous post.

Second: This time, I also tried going to a nonexistent file in the same directory as the Hello World-ish index.php. The same thing happened - i.e. the process hung indefinitely.

I should also explicitly note a couple things (regarding this "without frankenphp directive" state) that I did not note in the earlier message:

  1. No log messages occurred (other than normal startup messages).
  2. While everything besides the PHP site works fine, that's only until I try to go to something on the PHP site. After I go to the PHP site, requests to other sites also hang.
dunglas commented 3 weeks ago

You need to compile PHP with ZTS support (and some other options) to use FrankenPHP: https://frankenphp.dev/docs/compile/#linux

These are Linux instructions, but they also work on FreeBSD.

For Brotli, it's to support a modern HTTP compression format. It's currently not optional (but it's on my todo list to make this dependency optional), it's weird that you don't get an error. You can download the lib from https://github.com/google/brotli (it's likely also available in ports).

In your case, you don't have to create a worker (it's standard PHP code). You can remove this line.

rwv37 commented 3 weeks ago

Thanks.

When you say:

In your case, you don't have to create a worker (it's standard PHP code). You can remove this line.

Do you mean "this line" specifically the worker line? That is, do I need a frankenphp directive even though there will be nothing in it after removing the worker line? Or should I just leave out the entire frankenphp directive?

Regarding brotli: I do have it installed on my machine (almost certainly due to it being a dependency of something, rather than being something that I installed knowingly). If I get a chance, I'll spend a little time looking into that -- maybe there's a build option for that to control whether header files are installed, for example.

dunglas commented 3 weeks ago

You need to keep the empty frankenphp directive.

rwv37 commented 3 weeks ago

OK, I'm sorry, but to make any further progress, I would have to spend a lot more time than I have trying to learn various things with which I'm essentially completely unfamiliar. However, I did make some progress, so before giving up, I'd like to note it here in the hopes that it might help someone else wants to give it a shot:

(1) I added #include <pthread.h> to frankenphp.c, inside of the same #elif defined(__FreeBSD__) || defined(__OpenBSD__) block as the existing #include <pthread_np.h>. That change alone got it past the original problem I mentioned in this thread.

(2) Before xcaddy compilation, I set the environment variable CGO_CPPFLAGS to '-I/usr/local/include'. That allowed brotli/decode.h to be found, and now the whole thing compiled successfully.

(3) All in all, in addition to the CGO_CPPFLAGS, I also set the environment variables CGO_ENABLED to 1 (though I believe this is the default) and XCADDY_GO_BUILD_FLAGS to -ldflags '-w -s' (though it seems to me that this probably shouldn't matter, since those ldflags look to be just related to debugging support).

(4) I altered the build options for ports/php83 (using make config) to enable ZTS (corresponding to OPTIONS_SET+=ZTS in a makefile), since @dunglas said that ZTS is required. I also made sure that EMBED was on (which is the default, and which corresponds to OPTIONS_SET+=EMBED), in the hopes that this meant the same as the --enable-embed given in the Linux compilation instructions liked to earlier by @dunglas.

Please note that I did not enable or disable any options for the others given in those Linux instructions, i.e. --disable-zend-signals and --enable-zend-max-execution-timers, as I did not see any that obviously might correspond (at least not obviously to ignorant me).

Please also note that I did not enable or disable any for the extra ones given in the MacOS instructions (on the same page), i.e. --enable-embed=static, --disable-opcache-jit, --enable-static, --enable-shared=no, and --with-iconv=/opt/homebrew/opt/libiconv/, both for the same reason as in the Linux case and also because although I know that MacOS is somehow strongly related to FreeBSD, I don't know whether or not it's appropriate here, and @dunglas specifically mentioned the Linux instructions, not the MacOS instructions.

I'm guessing that the MacOS instructions' --enable-embed=static, --enable-static, and maybe even --enable-shared=no might effectively correspond to FreeBSD's OPTIONS_SET+=EMBED (which, again, is the default and which I made sure was set), but I don't know.

(5) After making the changes mentioned above in (4) to the PHP build options, I recompiled every PHP-related port on my machine. Most of them compiled successfully, but I ran into errors with several. These errors were all very similar to this example which I got while trying to build databases/php82-pdo_mysql (I know I said php83 earlier, but I copied and pasted this later, after having tried php82 instead; the php83 errors in my first try were essentially the same as these):

===>   Returning to build of php82-pdo_mysql-8.2.23
===>   php82-pdo_mysql-8.2.23 depends on file: /usr/local/lib/php/20220829/pdo.so - not found
===>   Installing existing package /packages/All/php82-pdo-8.2.23.pkg
Installing php82-pdo-8.2.23...
Extracting php82-pdo-8.2.23: .......... done
=====
Message from php82-pdo-8.2.23:

--
This file has been added to automatically load the installed extension:
/usr/local/etc/php/ext-20-pdo.ini.sample
===>   php82-pdo_mysql-8.2.23 depends on file: /usr/local/lib/php/20220829/pdo.so - not found
*** Error code 1

Stop.
make: stopped in /xports/databases/php82-pdo_mysql

The tl/dr there is: (A) php82-pdo_mysql depends on pdo.so; (B) pdo.so comes from the package php82-pdo; (C) The build tool (synth) has previously built php82-pdo successfully, and so installs it in the build environment, apparently successfully; (D) But then it still can't find pdo.so.

All in all I got this same sort of error in these packages for these .so files which are supposed to be included in these other packages:

(6) As a stab in the dark, I then uninstalled all php83 stuff and tried with php82 instead, but wound up with the same sorts of errors (as shown above).

(7) To verify that the PHP compilation problem is related to the config option change I made, I set them back to the defaults and recompiled. It all compiled fine (though of course this would still leave the "you need ZTS" problem).

I'm sorry I will be unable to continue on this (at least for the foreseeable future), but like I said further progress by me would require spending a lot more time than I currently have in order to learn about a bunch of things that I have virtually no detailed knowledge of. I hope that what I've found so far might help someone else, though.

dunglas commented 3 weeks ago

Thanks for the feedback. Would you mind opening a PR to add the needed header include?

IMHO, it will be easier to "manually" compile PHP from sources with ZTS enabled (and other extensions you need) using the "Linux" (actually, this should work on most UNIXes) instructions than recompiling all the ports.

I'll give it a try at some point, supporting FreeBSD is on my todo list. The main "issue" is that it's not supported by GitHub actions so it will be hard to test support continuously as we do for Linux and macOS.

rwv37 commented 3 weeks ago

Would you mind opening a PR to add the needed header include?

Unfortunately, one of the things I need to learn (although I imagine this might be a lot easier than the rest of them) is using git and github for pretty much anything but adding comments and such šŸ˜›

rwv37 commented 2 weeks ago

I coincidentally ran into something in another project (completely unrelated) that I wanted to change, so I figured with two, count 'em, two git-related things to do at the same time, now's as good a time as any to try to figure out git and github. I have only been actively avoiding doing this for about two decades now, so I consider myself an early adopter.

I have opened a pull request at #1058. I hope this helps, and I hope I didn't screw up somehow!