ci: add Super-Linter (#323)

This commit is contained in:
Kévin Dunglas
2023-12-01 17:26:21 +01:00
committed by GitHub
parent b675d09c49
commit c9bf9940d1
24 changed files with 847 additions and 720 deletions

1
.github/FUNDING.yml vendored
View File

@@ -1 +0,0 @@
github: dunglas

View File

@@ -1,3 +1,4 @@
---
name: Build Docker images
on:
pull_request:
@@ -31,10 +32,12 @@ jobs:
name: Create variants matrix
id: matrix
run: |
METADATA=$(docker buildx bake --print | jq -c)
echo "metadata=$METADATA" >> "$GITHUB_OUTPUT"
echo "variants=$(jq -c '.group.default.targets|map(sub("runner-|builder-"; ""))|unique' <<< $METADATA)" >> "$GITHUB_OUTPUT"
echo "platforms=$(jq -c 'first(.target[]) | .platforms' <<< $METADATA)" >> "$GITHUB_OUTPUT"
METADATA="$(docker buildx bake --print | jq -c)"
{
echo metadata="$METADATA"
echo variants="$(jq -c '.group.default.targets|map(sub("runner-|builder-"; ""))|unique' <<< "$METADATA")"
echo platforms="$(jq -c 'first(.target[]) | .platforms' <<< "$METADATA")"
} >> "$GITHUB_OUTPUT"
env:
LATEST: '1' # TODO: unset this variable when releasing the first stable version
SHA: ${{github.sha}}
@@ -107,10 +110,10 @@ jobs:
run: |
mkdir -p /tmp/metadata/builder /tmp/metadata/runner
builderDigest=$(jq -r '."builder-${{matrix.variant}}"."containerimage.digest"' <<< $METADATA)
builderDigest="$(jq -r '."builder-${{matrix.variant}}"."containerimage.digest"' <<< "$METADATA")"
touch "/tmp/metadata/builder/${builderDigest#sha256:}"
runnerDigest=$(jq -r '."runner-${{matrix.variant}}"."containerimage.digest"' <<< $METADATA)
runnerDigest="$(jq -r '."runner-${{matrix.variant}}"."containerimage.digest"' <<< "$METADATA")"
touch "/tmp/metadata/runner/${runnerDigest#sha256:}"
env:
METADATA: ${{steps.build.outputs.metadata}}
@@ -138,7 +141,7 @@ jobs:
continue-on-error: ${{fromJson(needs.prepare.outputs.push)}}
run: |
docker run --platform=${{matrix.platform}} --rm \
$(jq -r '."builder-${{matrix.variant}}"."containerimage.config.digest"' <<< $METADATA) \
"$(jq -r '."builder-${{matrix.variant}}"."containerimage.config.digest"' <<< "$METADATA")" \
sh -c 'go test ${{matrix.race}} -v ./... && cd caddy && go test ${{matrix.race}} -v ./...'
env:
METADATA: ${{steps.build.outputs.metadata}}
@@ -176,13 +179,12 @@ jobs:
name: Create manifest list and push
working-directory: /tmp/metadata
run: |
docker buildx imagetools create $(jq -cr '.target."${{matrix.target}}-${{matrix.variant}}".tags | map("-t " + .) | join(" ")' <<< $METADATA) \
$(printf 'dunglas/frankenphp@sha256:%s ' *)
docker buildx imagetools create "$(jq -cr '.target."${{matrix.target}}-${{matrix.variant}}".tags | map("-t " + .) | join(" ")' <<< "$METADATA")" \
"$(printf 'dunglas/frankenphp@sha256:%s ' *)"
env:
METADATA: ${{needs.prepare.outputs.metadata}}
-
name: Inspect image
run: |
docker buildx imagetools inspect $(jq -cr '.target."${{matrix.target}}-${{matrix.variant}}".tags | first' <<< $METADATA)
run: docker buildx imagetools inspect "$(jq -cr '.target."${{matrix.target}}-${{matrix.variant}}".tags | first' <<< "$METADATA")"
env:
METADATA: ${{needs.prepare.outputs.metadata}}

43
.github/workflows/lint.yaml vendored Normal file
View File

@@ -0,0 +1,43 @@
---
name: Lint Code Base
on:
pull_request:
branches:
- main
push:
branches:
- main
jobs:
build:
name: Lint Code Base
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
statuses: write
steps:
-
name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0
-
name: Lint Code Base
uses: super-linter/super-linter@v5
env:
VALIDATE_ALL_CODEBASE: true
DEFAULT_BRANCH: main
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
LINTER_RULES_PATH: /
FILTER_REGEX_EXCLUDE: '.*C-Thread-Pool/.*'
MARKDOWN_CONFIG_FILE: .markdown-lint.yaml
VALIDATE_CPP: false
VALIDATE_JSCPD: false
VALIDATE_GO: false
VALIDATE_PHP_PHPCS: false
VALIDATE_PHP_PHPSTAN: false
VALIDATE_PHP_PSALM: false
VALIDATE_TERRAGRUNT: false

View File

@@ -1,3 +1,4 @@
---
name: Build binary releases
on:
pull_request:
@@ -52,7 +53,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
name: Copy binary
run: docker cp $(docker create --name static-builder dunglas/frankenphp:static-builder):/go/src/app/dist/frankenphp-linux-x86_64 frankenphp-linux-x86_64 ; docker rm static-builder
run: docker cp "$(docker create --name static-builder dunglas/frankenphp:static-builder):/go/src/app/dist/frankenphp-linux-x86_64" frankenphp-linux-x86_64 ; docker rm static-builder
-
name: Upload asset
if: github.ref_type == 'tag'

View File

@@ -1,3 +1,4 @@
---
name: Tests
on:
pull_request:
@@ -52,3 +53,8 @@ jobs:
name: Run Caddy module tests
working-directory: caddy/
run: go test -race -v ./...
-
name: Lint Go code
uses: golangci/golangci-lint-action@v3
with:
version: latest

6
.hadolint.yaml Normal file
View File

@@ -0,0 +1,6 @@
---
ignored:
- DL3006
- DL3008
- DL3018
- DL3022

4
.markdown-lint.yaml Normal file
View File

@@ -0,0 +1,4 @@
---
no-hard-tabs: false
MD013: false
MD033: false

View File

@@ -1,15 +1,20 @@
# Contributing
## Compiling PHP
### With Docker (Linux)
Build the dev Docker image:
docker build -t frankenphp-dev -f dev.Dockerfile .
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 8080:8080 -p 443:443 -v $PWD:/go/src/app -it frankenphp-dev
```console
docker build -t frankenphp-dev -f dev.Dockerfile .
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 8080:8080 -p 443:443 -v $PWD:/go/src/app -it frankenphp-dev
```
The image contains the usual development tools (Go, GDB, Valgrind, Neovim...).
If docker version is lower than 23.0, build is failed by dockerignore [pattern issue](https://github.com/moby/moby/pull/42676). Add directories to `.dockerignore`.
```patch
!testdata/*.php
!testdata/*.txt
@@ -24,65 +29,79 @@ If docker version is lower than 23.0, build is failed by dockerignore [pattern i
## Running the test suite
go test -race -v ./...
```console
go test -race -v ./...
```
## Caddy module
Build Caddy with the FrankenPHP Caddy module:
cd caddy/frankenphp/
go build
cd ../../
```console
cd caddy/frankenphp/
go build
cd ../../
```
Run the Caddy with the FrankenPHP Caddy module:
cd testdata/
../caddy/frankenphp/frankenphp run
```console
cd testdata/
../caddy/frankenphp/frankenphp run
```
The server is listening on `127.0.0.1:8080`:
curl -vk https://localhost/phpinfo.php
```console
curl -vk https://localhost/phpinfo.php
```
## Minimal test server
Build the minimal test server:
cd internal/testserver/
go build
cd ../../
```console
cd internal/testserver/
go build
cd ../../
```
Run the test server:
cd testdata/
../internal/testserver/testserver
```console
cd testdata/
../internal/testserver/testserver
```
The server is listening on `127.0.0.1:8080`:
curl -v http://127.0.0.1:8080/phpinfo.php
```console
curl -v http://127.0.0.1:8080/phpinfo.php
```
# Building Docker Images Locally
## Building Docker Images Locally
Print bake plan:
```
```console
docker buildx bake -f docker-bake.hcl --print
```
Build FrankenPHP images for amd64 locally:
```
```console
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/amd64"
```
Build FrankenPHP images for arm64 locally:
```
```console
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/arm64"
```
Build FrankenPHP images from scratch for arm64 & amd64 and push to Docker Hub:
```
```console
docker buildx bake -f docker-bake.hcl --pull --no-cache --push
```
@@ -90,6 +109,7 @@ docker buildx bake -f docker-bake.hcl --pull --no-cache --push
1. Open `.github/workflows/tests.yml`
2. Enable PHP debug symbols
```patch
- uses: shivammathur/setup-php@v2
# ...
@@ -97,7 +117,9 @@ docker buildx bake -f docker-bake.hcl --pull --no-cache --push
phpts: ts
+ debug: true
```
3. Enable `tmate` to connect to the container
```patch
-
name: Set CGO flags
@@ -110,19 +132,24 @@ docker buildx bake -f docker-bake.hcl --pull --no-cache --push
+ -
+ uses: mxschmitt/action-tmate@v3
```
4. Connect to the container
5. Open `frankenphp.go`
6. Enable `cgosymbolizer`
```patch
- //_ "github.com/ianlancetaylor/cgosymbolizer"
+ _ "github.com/ianlancetaylor/cgosymbolizer"
```
7. Download the module: `go get`
8. In the container, you can use GDB and the like:
```sh
```console
go test -c -ldflags=-w
gdb --args ./frankenphp.test -test.run ^MyTest$
```
9. When the bug is fixed, revert all these changes
## Misc Dev Resources
@@ -142,10 +169,9 @@ docker buildx bake -f docker-bake.hcl --pull --no-cache --push
* [Bake file definition](https://docs.docker.com/build/customize/bake/file-definition/)
* [docker buildx build](https://docs.docker.com/engine/reference/commandline/buildx_build/)
## Useful Command
```
```console
apk add strace util-linux gdb
strace -e 'trace=!futex,epoll_ctl,epoll_pwait,tgkill,rt_sigreturn' -p 1
```

View File

@@ -46,6 +46,7 @@ LABEL org.opencontainers.image.vendor="Kévin Dunglas"
FROM common AS builder
ARG FRANKENPHP_VERSION='dev'
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
COPY --from=golang-base /usr/local/go /usr/local/go
@@ -71,12 +72,11 @@ WORKDIR /go/src/app
COPY --link go.mod go.sum ./
RUN go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
RUN mkdir caddy && cd caddy
COPY --link caddy/go.mod caddy/go.sum ./caddy/
RUN cd caddy && \
go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
WORKDIR /go/src/app/caddy
COPY --link caddy/go.mod caddy/go.sum ./
RUN go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
WORKDIR /go/src/app
COPY --link *.* ./
COPY --link caddy caddy
COPY --link C-Thread-Pool C-Thread-Pool
@@ -87,12 +87,14 @@ COPY --link testdata testdata
# see https://github.com/docker-library/php/blob/master/8.2/bookworm/zts/Dockerfile#L57-L59 for PHP values
ENV CGO_LDFLAGS="-lssl -lcrypto -lreadline -largon2 -lcurl -lonig -lz $PHP_LDFLAGS" CGO_CFLAGS="-DFRANKENPHP_VERSION=$FRANKENPHP_VERSION $PHP_CFLAGS" CGO_CPPFLAGS=$PHP_CPPFLAGS
RUN cd caddy/frankenphp && \
GOBIN=/usr/local/bin go install -ldflags "-X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" && \
WORKDIR /go/src/app/caddy/frankenphp
RUN GOBIN=/usr/local/bin go install -ldflags "-X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" && \
setcap cap_net_bind_service=+ep /usr/local/bin/frankenphp && \
cp Caddyfile /etc/caddy/Caddyfile && \
frankenphp version
WORKDIR /go/src/app
FROM common AS runner

View File

@@ -6,7 +6,7 @@ FrankenPHP is a modern application server for PHP built on top of the [Caddy](ht
FrankenPHP gives superpowers to your PHP apps thanks to its stunning features: [*Early Hints*](docs/early-hints.md), [worker mode](docs/worker.md), [real-time capabilities](docs/mercure.md), automatic HTTPS, HTTP/2, and HTTP/3 support...
FrankenPHP works with any PHP app and makes your Symfony projects faster than ever thanks to provided integration with the worker mode (Laravel Octane support coming).
FrankenPHP works with any PHP app and makes your Symfony projects faster than ever thanks to the provided integration with the worker mode (Laravel Octane support coming).
FrankenPHP can also be used as a standalone Go library to embed PHP in any app using `net/http`.

View File

@@ -43,11 +43,13 @@ LABEL org.opencontainers.image.vendor="Kévin Dunglas"
FROM common AS builder
ARG FRANKENPHP_VERSION='dev'
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
COPY --link --from=golang-base /usr/local/go /usr/local/go
ENV PATH /usr/local/go/bin:$PATH
# hadolint ignore=SC2086
RUN apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
argon2-dev \
@@ -67,11 +69,11 @@ WORKDIR /go/src/app
COPY --link go.mod go.sum ./
RUN go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
RUN mkdir caddy && cd caddy
COPY caddy/go.mod caddy/go.sum ./caddy/
RUN cd caddy && go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
WORKDIR /go/src/app/caddy
COPY caddy/go.mod caddy/go.sum ./
RUN go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
WORKDIR /go/src/app
COPY --link *.* ./
COPY --link caddy caddy
COPY --link C-Thread-Pool C-Thread-Pool
@@ -82,11 +84,13 @@ COPY --link testdata testdata
# see https://github.com/docker-library/php/blob/master/8.2/bookworm/zts/Dockerfile#L57-L59 for php values
ENV CGO_LDFLAGS="-lssl -lcrypto -lreadline -largon2 -lcurl -lonig -lz $PHP_LDFLAGS" CGO_CFLAGS="-DFRANKENPHP_VERSION=$FRANKENPHP_VERSION $PHP_CFLAGS" CGO_CPPFLAGS=$PHP_CPPFLAGS
RUN cd caddy/frankenphp && \
GOBIN=/usr/local/bin go install -ldflags "-extldflags '-Wl,-z,stack-size=0x80000' -X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" && \
WORKDIR /go/src/app/caddy/frankenphp
RUN GOBIN=/usr/local/bin go install -ldflags "-extldflags '-Wl,-z,stack-size=0x80000' -X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" && \
setcap cap_net_bind_service=+ep /usr/local/bin/frankenphp && \
frankenphp version
WORKDIR /go/src/app
FROM common AS runner

View File

@@ -1,7 +1,6 @@
#!/bin/sh
set -o errexit
trap 'echo "Aborting due to errexit on line $LINENO. Exit code: $?" >&2' ERR
set -o xtrace
if ! type "git" > /dev/null; then
@@ -38,7 +37,13 @@ if [ -z "$FRANKENPHP_VERSION" ]; then
elif [ -d ".git/" ]; then
CURRENT_REF="$(git rev-parse --abbrev-ref HEAD)"
export CURRENT_REF
if echo "$FRANKENPHP_VERSION" | grep -F -q "."; then
# Tag
git checkout "v$FRANKENPHP_VERSION"
else
git checkout "$FRANKENPHP_VERSION"
fi
fi
bin="frankenphp-$os-$arch"
@@ -72,6 +77,7 @@ fi
./bin/spc doctor
./bin/spc fetch --with-php="$PHP_VERSION" --for-extensions="$PHP_EXTENSIONS"
# shellcheck disable=SC2086
./bin/spc build --enable-zts --build-embed $extraOpts "$PHP_EXTENSIONS" --with-libs="$PHP_EXTENSION_LIBS"
CGO_CFLAGS="-DFRANKENPHP_VERSION=$FRANKENPHP_VERSION $(./buildroot/bin/php-config --includes | sed s#-I/#-I"$PWD"/buildroot/#g)"
export CGO_CFLAGS

View File

@@ -37,8 +37,8 @@ RUN apk add --no-cache \
libtool && \
echo 'set auto-load safe-path /' > /root/.gdbinit
RUN git clone --branch=PHP-8.3 https://github.com/php/php-src.git && \
cd php-src && \
WORKDIR /usr/local/src/php
RUN git clone --branch=PHP-8.3 https://github.com/php/php-src.git . && \
# --enable-embed is only necessary to generate libphp.so, we don't use this SAPI directly
./buildconf --force && \
./configure \
@@ -47,18 +47,19 @@ RUN git clone --branch=PHP-8.3 https://github.com/php/php-src.git && \
--disable-zend-signals \
--enable-zend-max-execution-timers \
--enable-debug && \
make -j$(nproc) && \
make -j"$(nproc)" && \
make install && \
ldconfig /etc/ld.so.conf.d && \
cp php.ini-development /usr/local/lib/php.ini && \
echo -e "zend_extension=opcache.so\nopcache.enable=1" >> /usr/local/lib/php.ini &&\
echo "zend_extension=opcache.so" >> /usr/local/lib/php.ini && \
echo "opcache.enable=1" >> /usr/local/lib/php.ini && \
php --version
WORKDIR /go/src/app
COPY . .
RUN cd caddy/frankenphp && \
go build
WORKDIR /go/src/app/caddy/frankenphp
RUN go build
WORKDIR /go/src/app
CMD [ "zsh" ]

View File

@@ -13,6 +13,7 @@ ENV PHPIZE_DEPS \
pkg-config \
re2c
# hadolint ignore=DL3009
RUN apt-get update && \
apt-get -y --no-install-recommends install \
$PHPIZE_DEPS \
@@ -41,8 +42,8 @@ RUN apt-get update && \
&& \
apt-get clean
RUN git clone --branch=PHP-8.3 https://github.com/php/php-src.git && \
cd php-src && \
WORKDIR /usr/local/src/php
RUN git clone --branch=PHP-8.3 https://github.com/php/php-src.git . && \
# --enable-embed is only necessary to generate libphp.so, we don't use this SAPI directly
./buildconf --force && \
./configure \
@@ -51,18 +52,19 @@ RUN git clone --branch=PHP-8.3 https://github.com/php/php-src.git && \
--disable-zend-signals \
--enable-zend-max-execution-timers \
--enable-debug && \
make -j$(nproc) && \
make -j"$(nproc)" && \
make install && \
ldconfig && \
cp php.ini-development /usr/local/lib/php.ini && \
echo "zend_extension=opcache.so\nopcache.enable=1" >> /usr/local/lib/php.ini &&\
echo "zend_extension=opcache.so" >> /usr/local/lib/php.ini && \
echo "opcache.enable=1" >> /usr/local/lib/php.ini && \
php --version
WORKDIR /go/src/app
COPY . .
RUN cd caddy/frankenphp && \
go build
WORKDIR /go/src/app/caddy/frankenphp
RUN go build
WORKDIR /go/src/app
CMD [ "zsh" ]

View File

@@ -15,8 +15,8 @@ COPY . /app/public
Then, run the commands to build and run the Docker image:
```console
$ docker build -t my-php-app .
$ docker run -it --rm --name my-running-app my-php-app
docker build -t my-php-app .
docker run -it --rm --name my-running-app my-php-app
```
## How to Install More PHP Extensions
@@ -70,7 +70,7 @@ COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp
The `builder` image provided by FrankenPHP contains a compiled version of libphp.
[Builders images](https://hub.docker.com/r/dunglas/frankenphp/tags?name=builder) are provided for all versions of FrankenPHP and PHP, both for Alpine and Debian.
# Enabling the Worker Mode by Default
## Enabling the Worker Mode by Default
Set the `FRANKENPHP_CONFIG` environment variable to start FrankenPHP with a worker script:
@@ -82,7 +82,7 @@ FROM dunglas/frankenphp
ENV FRANKENPHP_CONFIG="worker ./public/index.php"
```
# Using a Volume in Development
## Using a Volume in Development
To develop easily with FrankenPHP, mount the directory from your host containing the source code of the app as a volume in the Docker container:

View File

@@ -6,7 +6,6 @@ Calling PHP functions and language constructs that themselves call [cgo](https:/
This issue [is being worked on by the Go project](https://github.com/golang/go/issues/62130).
In the meantime, one solution is not to use constructs (like `echo`) and functions (like `header()`) that delegate to Go from inside Fibers.
This code will likely crash because it uses `echo` in the Fiber:

View File

@@ -18,20 +18,22 @@ Alternatively, you can run your Laravel projects with FrankenPHP from your local
1. [Download the binary corresponding to your system](https://github.com/dunglas/frankenphp/releases)
2. Add the following configuration to a file named `Caddyfile` in the root directory of your Laravel project:
```caddyfile
{
```caddyfile
{
frankenphp
order php_server before file_server
}
}
# The domain name of your server
localhost {
# The domain name of your server
localhost {
# Enable compression (optional)
encode zstd gzip
# Execute PHP files in the current directory and serve assets
php_server
}
```
}
```
3. Start FrankenPHP from the root directory of your Laravel project: `./frankenphp run`
## Laravel Octane

View File

@@ -7,6 +7,6 @@ No JS library or SDK required!
![Mercure](https://mercure.rocks/static/main.png)
To enable the Mercure hub, update the `Caddyfile` as described [on Mercure's website](https://mercure.rocks/docs/hub/config).
To enable the Mercure hub, update the `Caddyfile` as described [on Mercure's site](https://mercure.rocks/docs/hub/config).
To push Mercure updates from your code, we recommend the [Symfony Mercure Component](https://symfony.com/components/Mercure) (you don't need the Symfony full stack framework to use it).

View File

@@ -1,52 +1,44 @@
#include <SAPI.h>
#include <Zend/zend_alloc.h>
#include <Zend/zend_exceptions.h>
#include <Zend/zend_interfaces.h>
#include <Zend/zend_types.h>
#include <errno.h>
#include <ext/spl/spl_exceptions.h>
#include <ext/standard/head.h>
#include <php.h>
#include <php_config.h>
#include <php_main.h>
#include <php_output.h>
#include <php_variables.h>
#include <sapi/embed/php_embed.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <php_config.h>
#include <php.h>
#include <php_main.h>
#include <php_variables.h>
#include <php_output.h>
#include <SAPI.h>
#include <Zend/zend_alloc.h>
#include <Zend/zend_types.h>
#include <Zend/zend_exceptions.h>
#include <Zend/zend_interfaces.h>
#include <sapi/embed/php_embed.h>
#include <ext/standard/head.h>
#include <ext/spl/spl_exceptions.h>
#include "C-Thread-Pool/thpool.h"
#include "C-Thread-Pool/thpool.c"
#include "C-Thread-Pool/thpool.h"
#include "frankenphp_arginfo.h"
#include "_cgo_export.h"
#include "frankenphp_arginfo.h"
#if defined(PHP_WIN32) && defined(ZTS)
ZEND_TSRMLS_CACHE_DEFINE()
#endif
/* Timeouts are currently fundamentally broken with ZTS except on Linux: https://bugs.php.net/bug.php?id=79464 */
/* Timeouts are currently fundamentally broken with ZTS except on Linux:
* https://bugs.php.net/bug.php?id=79464 */
#ifndef ZEND_MAX_EXECUTION_TIMERS
static const char HARDCODED_INI[] =
"max_execution_time=0\n"
static const char HARDCODED_INI[] = "max_execution_time=0\n"
"max_input_time=-1\n\0";
#endif
static const char *MODULES_TO_RELOAD[] = {
"filter",
"session",
NULL
};
static const char *MODULES_TO_RELOAD[] = {"filter", "session", NULL};
frankenphp_version frankenphp_get_version() {
return (frankenphp_version){
PHP_MAJOR_VERSION,
PHP_MINOR_VERSION,
PHP_RELEASE_VERSION,
PHP_EXTRA_VERSION,
PHP_VERSION,
PHP_VERSION_ID,
PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION,
PHP_EXTRA_VERSION, PHP_VERSION, PHP_VERSION_ID,
};
}
@@ -91,13 +83,13 @@ static uintptr_t frankenphp_clean_server_context() {
free(SG(request_info).auth_user);
SG(request_info).auth_user = NULL;
free((char *) SG(request_info).request_method);
free((char *)SG(request_info).request_method);
SG(request_info).request_method = NULL;
free(SG(request_info).query_string);
SG(request_info).query_string = NULL;
free((char *) SG(request_info).content_type);
free((char *)SG(request_info).content_type);
SG(request_info).content_type = NULL;
free(SG(request_info).path_translated);
@@ -113,43 +105,43 @@ static void frankenphp_request_reset() {
zend_try {
int i;
for (i=0; i<NUM_TRACK_VARS; i++) {
for (i = 0; i < NUM_TRACK_VARS; i++) {
zval_ptr_dtor(&PG(http_globals)[i]);
}
memset(&PG(http_globals), 0, sizeof(zval) * NUM_TRACK_VARS);
} zend_end_try();
}
zend_end_try();
}
/* Adapted from php_request_shutdown */
static void frankenphp_worker_request_shutdown() {
/* Flush all output buffers */
zend_try {
php_output_end_all();
} zend_end_try();
zend_try { php_output_end_all(); }
zend_end_try();
// TODO: store the list of modules to reload in a global module variable
const char **module_name;
zend_module_entry *module;
for (module_name = MODULES_TO_RELOAD; *module_name; module_name++) {
if ((module = zend_hash_str_find_ptr(&module_registry, *module_name, strlen(*module_name)))) {
if ((module = zend_hash_str_find_ptr(&module_registry, *module_name,
strlen(*module_name)))) {
module->request_shutdown_func(module->type, module->module_number);
}
}
/* Shutdown output layer (send the set HTTP headers, cleanup output handlers, etc.) */
zend_try {
php_output_deactivate();
} zend_end_try();
/* Shutdown output layer (send the set HTTP headers, cleanup output handlers,
* etc.) */
zend_try { php_output_deactivate(); }
zend_end_try();
/* Clean super globals */
frankenphp_request_reset();
/* SAPI related shutdown (free stuff) */
frankenphp_clean_server_context();
zend_try {
sapi_deactivate();
} zend_end_try();
zend_try { sapi_deactivate(); }
zend_end_try();
zend_set_memory_limit(PG(memory_limit));
}
@@ -169,7 +161,8 @@ static int frankenphp_worker_request_startup() {
sapi_activate();
/*
* Timeouts are currently fundamentally broken with ZTS: https://bugs.php.net/bug.php?id=79464
* Timeouts are currently fundamentally broken with ZTS:
*https://bugs.php.net/bug.php?id=79464
*
*if (PG(max_input_time) == -1) {
* zend_set_timeout(EG(timeout_seconds), 1);
@@ -179,7 +172,8 @@ static int frankenphp_worker_request_startup() {
*/
if (PG(expose_php)) {
sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1);
sapi_add_header(SAPI_PHP_VERSION_HEADER,
sizeof(SAPI_PHP_VERSION_HEADER) - 1, 1);
}
if (PG(output_handler) && PG(output_handler)[0]) {
@@ -189,7 +183,9 @@ static int frankenphp_worker_request_startup() {
php_output_start_user(&oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS);
zval_ptr_dtor(&oh);
} else if (PG(output_buffering)) {
php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS);
php_output_start_user(NULL,
PG(output_buffering) > 1 ? PG(output_buffering) : 0,
PHP_OUTPUT_HANDLER_STDFLAGS);
} else if (PG(implicit_flush)) {
php_output_set_implicit_flush(1);
}
@@ -206,16 +202,15 @@ static int frankenphp_worker_request_startup() {
const char **module_name;
zend_module_entry *module;
for (module_name = MODULES_TO_RELOAD; *module_name; module_name++) {
if (
(module = zend_hash_str_find_ptr(&module_registry, *module_name, sizeof(*module_name)-1))
&& module->request_startup_func
) {
if ((module = zend_hash_str_find_ptr(&module_registry, *module_name,
sizeof(*module_name) - 1)) &&
module->request_startup_func) {
module->request_startup_func(module->type, module->module_number);
}
}
} zend_catch {
retval = FAILURE;
} zend_end_try();
}
zend_catch { retval = FAILURE; }
zend_end_try();
SG(sapi_started) = 1;
@@ -237,7 +232,8 @@ PHP_FUNCTION(frankenphp_finish_request) { /* {{{ */
php_header();
if (ctx->current_request != 0) {
go_frankenphp_finish_request(ctx->main_request, ctx->current_request, false);
go_frankenphp_finish_request(ctx->main_request, ctx->current_request,
false);
}
ctx->finished = true;
@@ -257,7 +253,9 @@ PHP_FUNCTION(frankenphp_handle_request) {
if (ctx->main_request == 0) {
// not a worker, throw an error
zend_throw_exception(spl_ce_RuntimeException, "frankenphp_handle_request() called while not in worker mode", 0);
zend_throw_exception(
spl_ce_RuntimeException,
"frankenphp_handle_request() called while not in worker mode", 0);
RETURN_THROWS();
}
@@ -276,12 +274,11 @@ PHP_FUNCTION(frankenphp_handle_request) {
zend_unset_timeout();
#endif
uintptr_t request = go_frankenphp_worker_handle_request_start(ctx->main_request);
if (
frankenphp_worker_request_startup() == FAILURE
uintptr_t request =
go_frankenphp_worker_handle_request_start(ctx->main_request);
if (frankenphp_worker_request_startup() == FAILURE
/* Shutting down */
|| !request
) {
|| !request) {
RETURN_FALSE;
}
@@ -299,7 +296,8 @@ PHP_FUNCTION(frankenphp_handle_request) {
zval_ptr_dtor(&retval);
}
/* If an exception occured, print the message to the client before closing the connection */
/* If an exception occured, print the message to the client before closing the
* connection */
if (EG(exception)) {
zend_exception_error(EG(exception), E_ERROR);
}
@@ -342,21 +340,19 @@ static zend_module_entry frankenphp_module = {
NULL, /* request shutdown */
NULL, /* information */
TOSTRING(FRANKENPHP_VERSION),
STANDARD_MODULE_PROPERTIES
};
STANDARD_MODULE_PROPERTIES};
static uintptr_t frankenphp_request_shutdown()
{
static uintptr_t frankenphp_request_shutdown() {
frankenphp_server_context *ctx = SG(server_context);
if (ctx->main_request && ctx->current_request) {
frankenphp_request_reset();
}
php_request_shutdown((void *) 0);
php_request_shutdown((void *)0);
free(ctx->cookie_data);
((frankenphp_server_context*) SG(server_context))->cookie_data = NULL;
((frankenphp_server_context *)SG(server_context))->cookie_data = NULL;
uintptr_t rh = frankenphp_clean_server_context();
free(ctx);
@@ -370,33 +366,25 @@ static uintptr_t frankenphp_request_shutdown()
}
int frankenphp_update_server_context(
bool create,
uintptr_t current_request,
uintptr_t main_request,
bool create, uintptr_t current_request, uintptr_t main_request,
const char *request_method,
char *query_string,
zend_long content_length,
char *path_translated,
char *request_uri,
const char *content_type,
char *auth_user,
char *auth_password,
int proto_num
) {
const char *request_method, char *query_string, zend_long content_length,
char *path_translated, char *request_uri, const char *content_type,
char *auth_user, char *auth_password, int proto_num) {
frankenphp_server_context *ctx;
if (create) {
#ifdef ZTS
/* initial resource fetch */
(void)ts_resource(0);
# ifdef PHP_WIN32
#ifdef PHP_WIN32
ZEND_TSRMLS_CACHE_UPDATE();
# endif
#endif
#endif
/* todo: use a pool */
ctx = (frankenphp_server_context *) calloc(1, sizeof(frankenphp_server_context));
ctx = (frankenphp_server_context *)calloc(
1, sizeof(frankenphp_server_context));
if (ctx == NULL) {
return FAILURE;
}
@@ -406,7 +394,7 @@ int frankenphp_update_server_context(
SG(server_context) = ctx;
} else {
ctx = (frankenphp_server_context *) SG(server_context);
ctx = (frankenphp_server_context *)SG(server_context);
}
ctx->main_request = main_request;
@@ -425,27 +413,26 @@ int frankenphp_update_server_context(
return SUCCESS;
}
static int frankenphp_startup(sapi_module_struct *sapi_module)
{
static int frankenphp_startup(sapi_module_struct *sapi_module) {
return php_module_startup(sapi_module, &frankenphp_module);
}
static int frankenphp_deactivate(void)
{
static int frankenphp_deactivate(void) {
/* TODO: flush everything */
return SUCCESS;
}
static size_t frankenphp_ub_write(const char *str, size_t str_length)
{
frankenphp_server_context* ctx = SG(server_context);
static size_t frankenphp_ub_write(const char *str, size_t str_length) {
frankenphp_server_context *ctx = SG(server_context);
if(ctx->finished) {
if (ctx->finished) {
// TODO: maybe log a warning that we tried to write to a finished request?
return 0;
}
struct go_ub_write_return result = go_ub_write(ctx->current_request ? ctx->current_request : ctx->main_request, (char *) str, str_length);
struct go_ub_write_return result = go_ub_write(
ctx->current_request ? ctx->current_request : ctx->main_request,
(char *)str, str_length);
if (result.r1) {
php_handle_aborted_connection();
@@ -454,14 +441,13 @@ static size_t frankenphp_ub_write(const char *str, size_t str_length)
return result.r0;
}
static int frankenphp_send_headers(sapi_headers_struct *sapi_headers)
{
static int frankenphp_send_headers(sapi_headers_struct *sapi_headers) {
if (SG(request_info).no_headers == 1) {
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
int status;
frankenphp_server_context* ctx = SG(server_context);
frankenphp_server_context *ctx = SG(server_context);
if (ctx->current_request == 0) {
return SAPI_HEADER_SEND_FAILED;
@@ -482,25 +468,24 @@ static int frankenphp_send_headers(sapi_headers_struct *sapi_headers)
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
static void frankenphp_sapi_flush(void *server_context)
{
frankenphp_server_context *ctx = (frankenphp_server_context *) server_context;
static void frankenphp_sapi_flush(void *server_context) {
frankenphp_server_context *ctx = (frankenphp_server_context *)server_context;
if (ctx && ctx->current_request != 0 && go_sapi_flush(ctx->current_request)) {
php_handle_aborted_connection();
}
}
static size_t frankenphp_read_post(char *buffer, size_t count_bytes)
{
frankenphp_server_context* ctx = SG(server_context);
static size_t frankenphp_read_post(char *buffer, size_t count_bytes) {
frankenphp_server_context *ctx = SG(server_context);
return ctx->current_request ? go_read_post(ctx->current_request, buffer, count_bytes) : 0;
return ctx->current_request
? go_read_post(ctx->current_request, buffer, count_bytes)
: 0;
}
static char* frankenphp_read_cookies(void)
{
frankenphp_server_context* ctx = SG(server_context);
static char *frankenphp_read_cookies(void) {
frankenphp_server_context *ctx = SG(server_context);
if (ctx->current_request == 0) {
return "";
@@ -511,14 +496,15 @@ static char* frankenphp_read_cookies(void)
return ctx->cookie_data;
}
static void frankenphp_register_known_variable(const char *key, char *value, zval *track_vars_array, bool f)
{
static void frankenphp_register_known_variable(const char *key, char *value,
zval *track_vars_array, bool f) {
if (value == NULL) {
return;
}
size_t new_val_len;
if (sapi_module.input_filter(PARSE_SERVER, key, &value, strlen(value), &new_val_len)) {
if (sapi_module.input_filter(PARSE_SERVER, key, &value, strlen(value),
&new_val_len)) {
php_register_variable_safe(key, value, new_val_len, track_vars_array);
}
@@ -528,66 +514,100 @@ static void frankenphp_register_known_variable(const char *key, char *value, zva
}
}
void frankenphp_register_bulk_variables(char *known_variables[27], char **dynamic_variables, size_t size, zval *track_vars_array)
{
void frankenphp_register_bulk_variables(char *known_variables[27],
char **dynamic_variables, size_t size,
zval *track_vars_array) {
/* Not used, but must be present */
frankenphp_register_known_variable("AUTH_TYPE", "", track_vars_array, false);
frankenphp_register_known_variable("REMOTE_IDENT", "", track_vars_array, false);
frankenphp_register_known_variable("REMOTE_IDENT", "", track_vars_array,
false);
/* Allocated in frankenphp_update_server_context() */
frankenphp_register_known_variable("CONTENT_TYPE", (char *) SG(request_info).content_type, track_vars_array, false);
frankenphp_register_known_variable("PATH_TRANSLATED", (char *) SG(request_info).path_translated, track_vars_array, false);
frankenphp_register_known_variable("QUERY_STRING", SG(request_info).query_string, track_vars_array, false);
frankenphp_register_known_variable("REMOTE_USER", (char *) SG(request_info).auth_user, track_vars_array, false);
frankenphp_register_known_variable("REQUEST_METHOD", (char *) SG(request_info).request_method, track_vars_array, false);
frankenphp_register_known_variable("REQUEST_URI", SG(request_info).request_uri, track_vars_array,false);
frankenphp_register_known_variable("CONTENT_TYPE",
(char *)SG(request_info).content_type,
track_vars_array, false);
frankenphp_register_known_variable("PATH_TRANSLATED",
(char *)SG(request_info).path_translated,
track_vars_array, false);
frankenphp_register_known_variable(
"QUERY_STRING", SG(request_info).query_string, track_vars_array, false);
frankenphp_register_known_variable("REMOTE_USER",
(char *)SG(request_info).auth_user,
track_vars_array, false);
frankenphp_register_known_variable("REQUEST_METHOD",
(char *)SG(request_info).request_method,
track_vars_array, false);
frankenphp_register_known_variable(
"REQUEST_URI", SG(request_info).request_uri, track_vars_array, false);
/* Known variables */
frankenphp_register_known_variable("CONTENT_LENGTH", known_variables[0], track_vars_array, true);
frankenphp_register_known_variable("DOCUMENT_ROOT", known_variables[1], track_vars_array, true);
frankenphp_register_known_variable("DOCUMENT_URI", known_variables[2], track_vars_array, true);
frankenphp_register_known_variable("GATEWAY_INTERFACE", known_variables[3], track_vars_array, true);
frankenphp_register_known_variable("HTTP_HOST", known_variables[4], track_vars_array, true);
frankenphp_register_known_variable("HTTPS", known_variables[5], track_vars_array, true);
frankenphp_register_known_variable("PATH_INFO", known_variables[6], track_vars_array, true);
frankenphp_register_known_variable("PHP_SELF", known_variables[7], track_vars_array, true);
frankenphp_register_known_variable("REMOTE_ADDR", known_variables[8], track_vars_array, known_variables[8] != known_variables[9]);
frankenphp_register_known_variable("REMOTE_HOST", known_variables[9], track_vars_array, true);
frankenphp_register_known_variable("REMOTE_PORT", known_variables[10], track_vars_array, true);
frankenphp_register_known_variable("REQUEST_SCHEME", known_variables[11], track_vars_array, true);
frankenphp_register_known_variable("SCRIPT_FILENAME", known_variables[12], track_vars_array, true);
frankenphp_register_known_variable("SCRIPT_NAME", known_variables[13], track_vars_array, true);
frankenphp_register_known_variable("SERVER_NAME", known_variables[14], track_vars_array, true);
frankenphp_register_known_variable("SERVER_PORT", known_variables[15], track_vars_array, true);
frankenphp_register_known_variable("SERVER_PROTOCOL", known_variables[16], track_vars_array, true);
frankenphp_register_known_variable("SERVER_SOFTWARE", known_variables[17], track_vars_array, true);
frankenphp_register_known_variable("SSL_PROTOCOL", known_variables[18], track_vars_array, true);
frankenphp_register_known_variable("CONTENT_LENGTH", known_variables[0],
track_vars_array, true);
frankenphp_register_known_variable("DOCUMENT_ROOT", known_variables[1],
track_vars_array, true);
frankenphp_register_known_variable("DOCUMENT_URI", known_variables[2],
track_vars_array, true);
frankenphp_register_known_variable("GATEWAY_INTERFACE", known_variables[3],
track_vars_array, true);
frankenphp_register_known_variable("HTTP_HOST", known_variables[4],
track_vars_array, true);
frankenphp_register_known_variable("HTTPS", known_variables[5],
track_vars_array, true);
frankenphp_register_known_variable("PATH_INFO", known_variables[6],
track_vars_array, true);
frankenphp_register_known_variable("PHP_SELF", known_variables[7],
track_vars_array, true);
frankenphp_register_known_variable("REMOTE_ADDR", known_variables[8],
track_vars_array,
known_variables[8] != known_variables[9]);
frankenphp_register_known_variable("REMOTE_HOST", known_variables[9],
track_vars_array, true);
frankenphp_register_known_variable("REMOTE_PORT", known_variables[10],
track_vars_array, true);
frankenphp_register_known_variable("REQUEST_SCHEME", known_variables[11],
track_vars_array, true);
frankenphp_register_known_variable("SCRIPT_FILENAME", known_variables[12],
track_vars_array, true);
frankenphp_register_known_variable("SCRIPT_NAME", known_variables[13],
track_vars_array, true);
frankenphp_register_known_variable("SERVER_NAME", known_variables[14],
track_vars_array, true);
frankenphp_register_known_variable("SERVER_PORT", known_variables[15],
track_vars_array, true);
frankenphp_register_known_variable("SERVER_PROTOCOL", known_variables[16],
track_vars_array, true);
frankenphp_register_known_variable("SERVER_SOFTWARE", known_variables[17],
track_vars_array, true);
frankenphp_register_known_variable("SSL_PROTOCOL", known_variables[18],
track_vars_array, true);
size_t new_val_len;
for (size_t i = 0; i < size; i = i+2)
{
if (sapi_module.input_filter(PARSE_SERVER, dynamic_variables[i], &dynamic_variables[i+1], strlen(dynamic_variables[i+1]), &new_val_len)) {
php_register_variable_safe(dynamic_variables[i], dynamic_variables[i+1], new_val_len, track_vars_array);
for (size_t i = 0; i < size; i = i + 2) {
if (sapi_module.input_filter(
PARSE_SERVER, dynamic_variables[i], &dynamic_variables[i + 1],
strlen(dynamic_variables[i + 1]), &new_val_len)) {
php_register_variable_safe(dynamic_variables[i], dynamic_variables[i + 1],
new_val_len, track_vars_array);
}
free(dynamic_variables[i]);
free(dynamic_variables[i+1]);
free(dynamic_variables[i + 1]);
}
free(dynamic_variables);
}
static void frankenphp_register_variables(zval *track_vars_array)
{
static void frankenphp_register_variables(zval *track_vars_array) {
/* https://www.php.net/manual/en/reserved.variables.server.php */
frankenphp_server_context* ctx = SG(server_context);
frankenphp_server_context *ctx = SG(server_context);
go_register_variables(ctx->current_request ? ctx->current_request : ctx->main_request, track_vars_array);
go_register_variables(ctx->current_request ? ctx->current_request
: ctx->main_request,
track_vars_array);
}
static void frankenphp_log_message(const char *message, int syslog_type_int)
{
go_log((char *) message, syslog_type_int);
static void frankenphp_log_message(const char *message, int syslog_type_int) {
go_log((char *)message, syslog_type_int);
}
sapi_module_struct frankenphp_sapi_module = {
@@ -619,38 +639,38 @@ sapi_module_struct frankenphp_sapi_module = {
NULL, /* Get request time */
NULL, /* Child terminate */
STANDARD_SAPI_MODULE_PROPERTIES
};
STANDARD_SAPI_MODULE_PROPERTIES};
static void *manager_thread(void *arg) {
#ifdef ZTS
// TODO: use tsrm_startup() directly as we know the number of expected threads
php_tsrm_startup();
/*tsrm_error_set(TSRM_ERROR_LEVEL_INFO, NULL);*/
# ifdef PHP_WIN32
#ifdef PHP_WIN32
ZEND_TSRMLS_CACHE_UPDATE();
# endif
#endif
#endif
sapi_startup(&frankenphp_sapi_module);
#ifndef ZEND_MAX_EXECUTION_TIMERS
# if (PHP_VERSION_ID >= 80300)
#if (PHP_VERSION_ID >= 80300)
frankenphp_sapi_module.ini_entries = HARDCODED_INI;
# else
#else
frankenphp_sapi_module.ini_entries = malloc(sizeof(HARDCODED_INI));
memcpy(frankenphp_sapi_module.ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI));
# endif
memcpy(frankenphp_sapi_module.ini_entries, HARDCODED_INI,
sizeof(HARDCODED_INI));
#endif
#endif
frankenphp_sapi_module.startup(&frankenphp_sapi_module);
threadpool thpool = thpool_init(*((int *) arg));
threadpool thpool = thpool_init(*((int *)arg));
free(arg);
uintptr_t rh;
while ((rh = go_fetch_request())) {
thpool_add_work(thpool, go_execute_script, (void *) rh);
thpool_add_work(thpool, go_execute_script, (void *)rh);
}
/* channel closed, shutdown gracefully */
@@ -682,7 +702,8 @@ int frankenphp_init(int num_threads) {
int *num_threads_ptr = calloc(1, sizeof(int));
*num_threads_ptr = num_threads;
if (pthread_create(&thread, NULL, *manager_thread, (void *) num_threads_ptr) != 0) {
if (pthread_create(&thread, NULL, *manager_thread, (void *)num_threads_ptr) !=
0) {
go_shutdown();
return -1;
@@ -691,8 +712,7 @@ int frankenphp_init(int num_threads) {
return pthread_detach(thread);
}
int frankenphp_request_startup()
{
int frankenphp_request_startup() {
if (php_request_startup() == SUCCESS) {
return SUCCESS;
}
@@ -701,13 +721,12 @@ int frankenphp_request_startup()
SG(server_context) = NULL;
free(ctx);
php_request_shutdown((void *) 0);
php_request_shutdown((void *)0);
return FAILURE;
}
int frankenphp_execute_script(char* file_name)
{
int frankenphp_execute_script(char *file_name) {
if (frankenphp_request_startup() == FAILURE) {
free(file_name);
@@ -726,9 +745,9 @@ int frankenphp_execute_script(char* file_name)
EG(exit_status) = 0;
php_execute_script(&file_handle);
status = EG(exit_status);
} zend_catch {
status = EG(exit_status);
} zend_end_try();
}
zend_catch { status = EG(exit_status); }
zend_end_try();
zend_destroy_file_handle(&file_handle);
@@ -743,21 +762,25 @@ static char *cli_script;
static int cli_argc;
static char **cli_argv;
// Adapted from https://github.com/php/php-src/sapi/cli/php_cli.c (The PHP Group, The PHP License)
// Adapted from https://github.com/php/php-src/sapi/cli/php_cli.c (The PHP
// Group, The PHP License)
static void cli_register_file_handles(bool no_close) /* {{{ */
{
php_stream *s_in, *s_out, *s_err;
php_stream_context *sc_in=NULL, *sc_out=NULL, *sc_err=NULL;
php_stream_context *sc_in = NULL, *sc_out = NULL, *sc_err = NULL;
zend_constant ic, oc, ec;
s_in = php_stream_open_wrapper_ex("php://stdin", "rb", 0, NULL, sc_in);
s_out = php_stream_open_wrapper_ex("php://stdout", "wb", 0, NULL, sc_out);
s_err = php_stream_open_wrapper_ex("php://stderr", "wb", 0, NULL, sc_err);
if (s_in==NULL || s_out==NULL || s_err==NULL) {
if (s_in) php_stream_close(s_in);
if (s_out) php_stream_close(s_out);
if (s_err) php_stream_close(s_err);
if (s_in == NULL || s_out == NULL || s_err == NULL) {
if (s_in)
php_stream_close(s_in);
if (s_out)
php_stream_close(s_out);
if (s_err)
php_stream_close(s_err);
return;
}
@@ -767,22 +790,22 @@ static void cli_register_file_handles(bool no_close) /* {{{ */
s_err->flags |= PHP_STREAM_FLAG_NO_CLOSE;
}
//s_in_process = s_in;
// s_in_process = s_in;
php_stream_to_zval(s_in, &ic.value);
php_stream_to_zval(s_out, &oc.value);
php_stream_to_zval(s_err, &ec.value);
ZEND_CONSTANT_SET_FLAGS(&ic, CONST_CS, 0);
ic.name = zend_string_init_interned("STDIN", sizeof("STDIN")-1, 0);
ic.name = zend_string_init_interned("STDIN", sizeof("STDIN") - 1, 0);
zend_register_constant(&ic);
ZEND_CONSTANT_SET_FLAGS(&oc, CONST_CS, 0);
oc.name = zend_string_init_interned("STDOUT", sizeof("STDOUT")-1, 0);
oc.name = zend_string_init_interned("STDOUT", sizeof("STDOUT") - 1, 0);
zend_register_constant(&oc);
ZEND_CONSTANT_SET_FLAGS(&ec, CONST_CS, 0);
ec.name = zend_string_init_interned("STDERR", sizeof("STDERR")-1, 0);
ec.name = zend_string_init_interned("STDERR", sizeof("STDERR") - 1, 0);
zend_register_constant(&ec);
}
/* }}} */
@@ -799,28 +822,36 @@ static void sapi_cli_register_variables(zval *track_vars_array) /* {{{ */
/* Build the special-case PHP_SELF variable for the CLI version */
len = strlen(cli_script);
if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &cli_script, len, &len)) {
if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &cli_script, len,
&len)) {
php_register_variable_safe("PHP_SELF", cli_script, len, track_vars_array);
}
if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME", &cli_script, len, &len)) {
php_register_variable_safe("SCRIPT_NAME", cli_script, len, track_vars_array);
if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME", &cli_script, len,
&len)) {
php_register_variable_safe("SCRIPT_NAME", cli_script, len,
track_vars_array);
}
/* filenames are empty for stdin */
if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME", &cli_script, len, &len)) {
php_register_variable_safe("SCRIPT_FILENAME", cli_script, len, track_vars_array);
if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME", &cli_script,
len, &len)) {
php_register_variable_safe("SCRIPT_FILENAME", cli_script, len,
track_vars_array);
}
if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED", &cli_script, len, &len)) {
php_register_variable_safe("PATH_TRANSLATED", cli_script, len, track_vars_array);
if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED", &cli_script,
len, &len)) {
php_register_variable_safe("PATH_TRANSLATED", cli_script, len,
track_vars_array);
}
/* just make it available */
len = 0U;
if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT", &docroot, len, &len)) {
if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT", &docroot, len,
&len)) {
php_register_variable_safe("DOCUMENT_ROOT", docroot, len, track_vars_array);
}
}
/* }}} */
static void * execute_script_cli(void *arg) {
static void *execute_script_cli(void *arg) {
void *exit_status;
// The SAPI name "cli" is hardcoded into too many programs... let's usurp it.
@@ -836,9 +867,10 @@ static void * execute_script_cli(void *arg) {
zend_stream_init_filename(&file_handle, cli_script);
php_execute_script(&file_handle);
} zend_end_try();
}
zend_end_try();
exit_status = (void *) (intptr_t) EG(exit_status);
exit_status = (void *)(intptr_t)EG(exit_status);
php_embed_shutdown();
@@ -854,7 +886,8 @@ int frankenphp_execute_script_cli(char *script, int argc, char **argv) {
cli_argc = argc;
cli_argv = argv;
// Start the script in a dedicated thread to prevent conflicts between Go and PHP signal handlers
// Start the script in a dedicated thread to prevent conflicts between Go and
// PHP signal handlers
err = pthread_create(&thread, NULL, execute_script_cli, NULL);
if (err != 0) {
return err;
@@ -865,6 +898,5 @@ int frankenphp_execute_script_cli(char *script, int argc, char **argv) {
return err;
}
return (intptr_t) exit_status;
return (intptr_t)exit_status;
}

View File

@@ -1,9 +1,9 @@
#ifndef _FRANKENPPHP_H
#define _FRANKENPPHP_H
#include <stdint.h>
#include <stdbool.h>
#include <Zend/zend_types.h>
#include <stdbool.h>
#include <stdint.h>
#ifndef FRANKENPHP_VERSION
#define FRANKENPHP_VERSION dev
@@ -32,23 +32,16 @@ frankenphp_config frankenphp_get_config();
int frankenphp_init(int num_threads);
int frankenphp_update_server_context(
bool create,
uintptr_t current_request,
uintptr_t main_request,
bool create, uintptr_t current_request, uintptr_t main_request,
const char *request_method,
char *query_string,
zend_long content_length,
char *path_translated,
char *request_uri,
const char *content_type,
char *auth_user,
char *auth_password,
int proto_num
);
const char *request_method, char *query_string, zend_long content_length,
char *path_translated, char *request_uri, const char *content_type,
char *auth_user, char *auth_password, int proto_num);
int frankenphp_request_startup();
int frankenphp_execute_script(char *file_name);
void frankenphp_register_bulk_variables(char *known_variables[27], char **dynamic_variables, size_t size, zval *track_vars_array);
void frankenphp_register_bulk_variables(char *known_variables[27],
char **dynamic_variables, size_t size,
zval *track_vars_array);
int frankenphp_execute_script_cli(char *script, int argc, char **argv);

View File

@@ -1,29 +1,28 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: de4dc4063fafd8c933e3068c8349889a7ece5f03 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_frankenphp_handle_request, 0, 1, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_frankenphp_handle_request, 0, 1,
_IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_headers_send, 0, 0, IS_LONG, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, status, IS_LONG, 0, "200")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, status, IS_LONG, 0, "200")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_frankenphp_finish_request, 0, 0, _IS_BOOL, 0)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_frankenphp_finish_request, 0, 0,
_IS_BOOL, 0)
ZEND_END_ARG_INFO()
#define arginfo_fastcgi_finish_request arginfo_frankenphp_finish_request
ZEND_FUNCTION(frankenphp_handle_request);
ZEND_FUNCTION(headers_send);
ZEND_FUNCTION(frankenphp_finish_request);
static const zend_function_entry ext_functions[] = {
ZEND_FE(frankenphp_handle_request, arginfo_frankenphp_handle_request)
ZEND_FE(headers_send, arginfo_headers_send)
ZEND_FE(frankenphp_finish_request, arginfo_frankenphp_finish_request)
ZEND_FALIAS(fastcgi_finish_request, frankenphp_finish_request, arginfo_fastcgi_finish_request)
ZEND_FE_END
};
ZEND_FE(headers_send, arginfo_headers_send) ZEND_FE(
frankenphp_finish_request, arginfo_frankenphp_finish_request)
ZEND_FALIAS(fastcgi_finish_request, frankenphp_finish_request,
arginfo_fastcgi_finish_request) ZEND_FE_END};

View File

@@ -5,6 +5,7 @@ ARG FRANKENPHP_VERSION=''
ARG PHP_VERSION=''
ARG PHP_EXTENSIONS=''
ARG PHP_EXTENSION_LIBS=''
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
RUN apk update; \
apk add --no-cache \
@@ -56,15 +57,14 @@ ENV PATH="${PATH}:/root/.composer/vendor/bin"
COPY --from=composer/composer:2-bin --link /composer /usr/bin/composer
WORKDIR /go/src/app
COPY go.mod go.sum ./
RUN go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
RUN mkdir caddy && cd caddy
COPY caddy/go.mod caddy/go.sum ./caddy/
RUN cd caddy && go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
WORKDIR /go/src/app/caddy
COPY caddy/go.mod caddy/go.sum ./
RUN go mod graph | awk '{if ($1 !~ "@") print $2}' | xargs go get
WORKDIR /go/src/app
COPY *.* ./
COPY caddy caddy
COPY C-Thread-Pool C-Thread-Pool