Compare commits
4 Commits
b0ffa8417c
...
2b4e6d3a4d
Author | SHA1 | Date | |
---|---|---|---|
2b4e6d3a4d | |||
d9e4b2e4d7 | |||
643514a9c7 | |||
7c2d19ed24 |
50
.github/workflows/ci-alpine.yml
vendored
Normal file
50
.github/workflows/ci-alpine.yml
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
name: "Checks (alpine, many platforms)"
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linux-alpine:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: linux-alpine-${{ matrix.platform }}
|
||||||
|
# abort if x86_64 fails
|
||||||
|
continue-on-error: ${{ matrix.platform != 'x86_64' }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
platform: ['x86_64','x86','armhf','armv7','aarch64','ppc64le','riscv64','s390x']
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: jirutka/setup-alpine@v1
|
||||||
|
with:
|
||||||
|
# riscv64 currently requires 'edge'
|
||||||
|
branch: edge
|
||||||
|
arch: ${{ matrix.platform }}
|
||||||
|
packages: >
|
||||||
|
build-base
|
||||||
|
meson
|
||||||
|
libev-dev
|
||||||
|
ragel
|
||||||
|
glib-dev
|
||||||
|
lua5.1-dev
|
||||||
|
zlib-dev
|
||||||
|
bzip2-dev
|
||||||
|
pkgconf
|
||||||
|
openssl-dev
|
||||||
|
gnutls-dev
|
||||||
|
libidn-dev
|
||||||
|
libunwind-dev
|
||||||
|
python3
|
||||||
|
py3-curl
|
||||||
|
- name: meson setup
|
||||||
|
shell: alpine.sh {0}
|
||||||
|
run: meson setup mesonbuilddir
|
||||||
|
- name: meson compile
|
||||||
|
shell: alpine.sh {0}
|
||||||
|
run: meson compile -C mesonbuilddir
|
||||||
|
- name: meson test
|
||||||
|
shell: alpine.sh {0}
|
||||||
|
run: meson test -C mesonbuilddir -v
|
67
.github/workflows/ci-linux.yml
vendored
Normal file
67
.github/workflows/ci-linux.yml
vendored
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
name: "Checks (Ubuntu: gcc+clang)"
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{github.workflow}}-${{github.head_ref}}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linux-build-docs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pkgs=(
|
||||||
|
ruby
|
||||||
|
ruby-nokogiri
|
||||||
|
ruby-kramdown
|
||||||
|
libxml2-utils
|
||||||
|
)
|
||||||
|
sudo apt-get install "${pkgs[@]}"
|
||||||
|
- name: Build docs
|
||||||
|
run: |
|
||||||
|
mkdir -p out
|
||||||
|
ruby doc/compile.rb out
|
||||||
|
cp doc/*.css doc/*.js out
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: lighttpd2-docs
|
||||||
|
path: out
|
||||||
|
|
||||||
|
linux-ubuntu:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: linux-ubuntu-${{ matrix.compiler }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
compiler: ['gcc', 'clang']
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- if: ${{ matrix.compiler == 'clang' }}
|
||||||
|
uses: egor-tensin/setup-clang@v1
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pkgs=(
|
||||||
|
meson
|
||||||
|
libev-dev
|
||||||
|
ragel
|
||||||
|
libglib2.0-dev
|
||||||
|
liblua5.1-dev
|
||||||
|
zlib1g-dev
|
||||||
|
libbz2-dev
|
||||||
|
pkg-config
|
||||||
|
libssl-dev
|
||||||
|
libgnutls28-dev
|
||||||
|
libidn-dev
|
||||||
|
libunwind8-dev
|
||||||
|
python3
|
||||||
|
python3-pycurl
|
||||||
|
)
|
||||||
|
sudo apt-get install "${pkgs[@]}"
|
||||||
|
- name: meson setup
|
||||||
|
run: meson setup mesonbuilddir
|
||||||
|
- name: meson compile
|
||||||
|
run: meson compile -C mesonbuilddir
|
||||||
|
- name: meson test
|
||||||
|
run: meson test -C mesonbuilddir -v
|
52
.github/workflows/ci-macos.yml
vendored
Normal file
52
.github/workflows/ci-macos.yml
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
name: "Checks (macOS)"
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{github.workflow}}-${{github.head_ref}}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
macOS:
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pkgs=(
|
||||||
|
meson
|
||||||
|
libev
|
||||||
|
ragel
|
||||||
|
glib
|
||||||
|
lua@5.1
|
||||||
|
zlib
|
||||||
|
bzip2
|
||||||
|
openssl@3
|
||||||
|
gnutls
|
||||||
|
libidn
|
||||||
|
python3
|
||||||
|
python-pycurl
|
||||||
|
md5sha1sum
|
||||||
|
)
|
||||||
|
brew install "${pkgs[@]}"
|
||||||
|
- name: meson setup
|
||||||
|
run: meson setup -D unwind=false mesonbuilddir
|
||||||
|
- name: meson compile
|
||||||
|
run: meson compile -C mesonbuilddir
|
||||||
|
- name: prepare environment for tests
|
||||||
|
run: |
|
||||||
|
sudo ifconfig lo0 alias 127.0.0.2 up
|
||||||
|
|
||||||
|
# try to create a tmpdir with a short relative path (for shorter unix socket paths)
|
||||||
|
NEWTMPDIR=~/tmp
|
||||||
|
ln -sf "${TMPDIR}" "${NEWTMPDIR}"
|
||||||
|
echo "TMPDIR=$NEWTMPDIR" >> "$GITHUB_ENV"
|
||||||
|
echo "PATH=$(brew --prefix python)/libexec/bin:$PATH" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
if [ ! -f $(brew --prefix python)/libexec/bin/python3 ]; then
|
||||||
|
# the brew path only provides "python", not "python3"...
|
||||||
|
ln -s python $(brew --prefix python)/libexec/bin/python3
|
||||||
|
fi
|
||||||
|
- name: meson test
|
||||||
|
run: |
|
||||||
|
meson test -C mesonbuilddir -v
|
@ -17,11 +17,16 @@
|
|||||||
|
|
||||||
/** see li_module_load */
|
/** see li_module_load */
|
||||||
#define MODULE_DEPENDS(mods, name) do { \
|
#define MODULE_DEPENDS(mods, name) do { \
|
||||||
if (!li_module_load(mods, name)) { \
|
GError *err = NULL; \
|
||||||
ERROR(mods->main, "Couldn't load dependency '%s'", name); \
|
if (!li_module_load(mods, name, &err)) { \
|
||||||
|
ERROR(mods->main, "Couldn't load dependency '%s': %s", name, err->message); \
|
||||||
|
g_error_free(err); \
|
||||||
return FALSE; \
|
return FALSE; \
|
||||||
} } while(0)
|
} } while(0)
|
||||||
|
|
||||||
|
#define LI_MODULES_ERROR li_modules_error_quark()
|
||||||
|
LI_API GQuark li_modules_error_quark(void);
|
||||||
|
|
||||||
typedef struct liModule liModule;
|
typedef struct liModule liModule;
|
||||||
|
|
||||||
typedef struct liModules liModules;
|
typedef struct liModules liModules;
|
||||||
@ -58,7 +63,7 @@ LI_API void li_modules_free(liModules *mods);
|
|||||||
* returns NULL if it couldn't load the module.
|
* returns NULL if it couldn't load the module.
|
||||||
*
|
*
|
||||||
* You should release modules after you used them with li_module_release or li_module_release_name */
|
* You should release modules after you used them with li_module_release or li_module_release_name */
|
||||||
LI_API liModule* li_module_load(liModules *mods, const gchar* name);
|
LI_API liModule* li_module_load(liModules *mods, const gchar* name, GError **error);
|
||||||
|
|
||||||
/* find module by name */
|
/* find module by name */
|
||||||
LI_API liModule *li_module_lookup(liModules *mods, const gchar *name);
|
LI_API liModule *li_module_lookup(liModules *mods, const gchar *name);
|
||||||
|
@ -230,6 +230,7 @@ gboolean li_plugins_load_module(liServer *srv, const gchar *name) {
|
|||||||
liPlugins *ps = &srv->plugins;
|
liPlugins *ps = &srv->plugins;
|
||||||
server_module *sm;
|
server_module *sm;
|
||||||
const gchar* modname = name ? name : "core";
|
const gchar* modname = name ? name : "core";
|
||||||
|
GError *err = NULL;
|
||||||
|
|
||||||
sm = g_hash_table_lookup(ps->module_refs, modname);
|
sm = g_hash_table_lookup(ps->module_refs, modname);
|
||||||
if (sm) return TRUE; /* already loaded */
|
if (sm) return TRUE; /* already loaded */
|
||||||
@ -240,9 +241,11 @@ gboolean li_plugins_load_module(liServer *srv, const gchar *name) {
|
|||||||
sm = server_module_new(srv, modname);
|
sm = server_module_new(srv, modname);
|
||||||
g_hash_table_insert(ps->module_refs, sm->name, sm);
|
g_hash_table_insert(ps->module_refs, sm->name, sm);
|
||||||
if (name) {
|
if (name) {
|
||||||
mod = li_module_load(ps->modules, name);
|
mod = li_module_load(ps->modules, name, &err);
|
||||||
|
|
||||||
if (!mod) {
|
if (!mod) {
|
||||||
|
ERROR(srv, "Couldn't load dependency '%s': %s", name, err->message);
|
||||||
|
g_error_free(err);
|
||||||
_server_module_release(sm);
|
_server_module_release(sm);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
#include <lighttpd/module.h>
|
#include <lighttpd/module.h>
|
||||||
#include <lighttpd/utils.h>
|
#include <lighttpd/utils.h>
|
||||||
|
|
||||||
|
GQuark li_modules_error_quark(void) {
|
||||||
|
return g_quark_from_string("li-modules-error-quark");
|
||||||
|
}
|
||||||
|
|
||||||
liModules *li_modules_new(gpointer main, const gchar *module_dir, gboolean module_resident) {
|
liModules *li_modules_new(gpointer main, const gchar *module_dir, gboolean module_resident) {
|
||||||
liModules *m = g_slice_new(liModules);
|
liModules *m = g_slice_new(liModules);
|
||||||
|
|
||||||
@ -48,7 +52,7 @@ void li_modules_free(liModules* mods) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
liModule* li_module_load(liModules *mods, const gchar* name) {
|
liModule* li_module_load(liModules *mods, const gchar* name, GError **err) {
|
||||||
liModule *mod;
|
liModule *mod;
|
||||||
liModuleInitCB m_init;
|
liModuleInitCB m_init;
|
||||||
GString *m_init_str, *m_free_str;
|
GString *m_init_str, *m_free_str;
|
||||||
@ -65,8 +69,15 @@ liModule* li_module_load(liModules *mods, const gchar* name) {
|
|||||||
mod = g_slice_new0(liModule);
|
mod = g_slice_new0(liModule);
|
||||||
mod->name = g_string_new(name);
|
mod->name = g_string_new(name);
|
||||||
mod->refcount = 1;
|
mod->refcount = 1;
|
||||||
mod->path = g_module_build_path(mods->module_dir, name);
|
|
||||||
|
|
||||||
|
mod->path = g_strconcat(mods->module_dir, G_DIR_SEPARATOR_S, name, NULL);
|
||||||
|
mod->module = g_module_open(mod->path, G_MODULE_BIND_LAZY);
|
||||||
|
|
||||||
|
if (!mod->module) {
|
||||||
|
if (err) g_set_error(err, LI_MODULES_ERROR, 1, "%s", g_module_error());
|
||||||
|
g_free(mod->path);
|
||||||
|
|
||||||
|
mod->path = g_module_build_path(mods->module_dir, name);
|
||||||
mod->module = g_module_open(mod->path, G_MODULE_BIND_LAZY);
|
mod->module = g_module_open(mod->path, G_MODULE_BIND_LAZY);
|
||||||
|
|
||||||
if (!mod->module) {
|
if (!mod->module) {
|
||||||
@ -75,6 +86,7 @@ liModule* li_module_load(liModules *mods, const gchar* name) {
|
|||||||
g_slice_free(liModule, mod);
|
g_slice_free(liModule, mod);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* temporary strings for mod_xyz_init and mod_xyz_free */
|
/* temporary strings for mod_xyz_init and mod_xyz_free */
|
||||||
m_init_str = g_string_new(name);
|
m_init_str = g_string_new(name);
|
||||||
@ -86,6 +98,12 @@ liModule* li_module_load(liModules *mods, const gchar* name) {
|
|||||||
|| !g_module_symbol(mod->module, m_free_str->str, (gpointer *)&mod->free)
|
|| !g_module_symbol(mod->module, m_free_str->str, (gpointer *)&mod->free)
|
||||||
|| m_init == NULL || mod->free == NULL) {
|
|| m_init == NULL || mod->free == NULL) {
|
||||||
|
|
||||||
|
g_set_error(err, LI_MODULES_ERROR, 1,
|
||||||
|
"li_module_load: couldn't load %s or %s from %s",
|
||||||
|
m_init_str->str,
|
||||||
|
m_free_str->str,
|
||||||
|
mod->path);
|
||||||
|
|
||||||
/* mod_init or mod_free couldn't be located, something went wrong */
|
/* mod_init or mod_free couldn't be located, something went wrong */
|
||||||
g_string_free(m_init_str, TRUE);
|
g_string_free(m_init_str, TRUE);
|
||||||
g_string_free(m_free_str, TRUE);
|
g_string_free(m_free_str, TRUE);
|
||||||
@ -97,6 +115,11 @@ liModule* li_module_load(liModules *mods, const gchar* name) {
|
|||||||
|
|
||||||
/* call mod_xyz_init */
|
/* call mod_xyz_init */
|
||||||
if (!m_init(mods, mod)) {
|
if (!m_init(mods, mod)) {
|
||||||
|
g_set_error(err, LI_MODULES_ERROR, 1,
|
||||||
|
"li_module_load: calling %s from %s failed",
|
||||||
|
m_init_str->str,
|
||||||
|
mod->path);
|
||||||
|
|
||||||
g_string_free(m_init_str, TRUE);
|
g_string_free(m_init_str, TRUE);
|
||||||
g_string_free(m_free_str, TRUE);
|
g_string_free(m_free_str, TRUE);
|
||||||
g_free(mod->path);
|
g_free(mod->path);
|
||||||
|
@ -1238,6 +1238,7 @@ static gboolean core_workers_cpu_affinity(liServer *srv, liPlugin* p, liValue *v
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean core_module_load(liServer *srv, liPlugin* p, liValue *val, gpointer userdata) {
|
static gboolean core_module_load(liServer *srv, liPlugin* p, liValue *val, gpointer userdata) {
|
||||||
|
GError *err = NULL;
|
||||||
UNUSED(p); UNUSED(userdata);
|
UNUSED(p); UNUSED(userdata);
|
||||||
|
|
||||||
if (!g_module_supported()) {
|
if (!g_module_supported()) {
|
||||||
@ -1272,8 +1273,9 @@ static gboolean core_module_load(liServer *srv, liPlugin* p, liValue *val, gpoin
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!li_module_load(srv->modules, name->str)) {
|
if (!li_module_load(srv->modules, name->str, &err)) {
|
||||||
ERROR(srv, "could not load module '%s': %s", name->str, g_module_error());
|
ERROR(srv, "could not load module '%s': %s", name->str, err->message);
|
||||||
|
g_error_free(err);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,15 @@ class Service:
|
|||||||
self.proc: typing.Optional[subprocess.Popen] = None
|
self.proc: typing.Optional[subprocess.Popen] = None
|
||||||
self.failed = False
|
self.failed = False
|
||||||
|
|
||||||
|
def bind_unix_socket(self, *, sockfile: str, backlog: int = 8) -> socket.socket:
|
||||||
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
|
rel_sockfile = os.path.relpath(sockfile)
|
||||||
|
if len(rel_sockfile) < len(sockfile):
|
||||||
|
sockfile = rel_sockfile
|
||||||
|
sock.bind(sockfile)
|
||||||
|
sock.listen(8)
|
||||||
|
return sock
|
||||||
|
|
||||||
def fork(self, *args: str, inp: typing.Union[tuple[()], FileWithFd, None] = ()) -> None:
|
def fork(self, *args: str, inp: typing.Union[tuple[()], FileWithFd, None] = ()) -> None:
|
||||||
arguments = list(args) # convert tuple to list
|
arguments = list(args) # convert tuple to list
|
||||||
stdin: typing.Optional[FileWithFd]
|
stdin: typing.Optional[FileWithFd]
|
||||||
@ -245,9 +254,7 @@ class FastCGI(Service):
|
|||||||
def prepare_service(self) -> None:
|
def prepare_service(self) -> None:
|
||||||
assert self.tests
|
assert self.tests
|
||||||
self.tests.install_dir(os.path.join("tmp", "sockets"))
|
self.tests.install_dir(os.path.join("tmp", "sockets"))
|
||||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
sock = self.bind_unix_socket(sockfile=self.sockfile)
|
||||||
sock.bind(os.path.relpath(self.sockfile))
|
|
||||||
sock.listen(8)
|
|
||||||
self.fork(*self.binary, inp=sock)
|
self.fork(*self.binary, inp=sock)
|
||||||
|
|
||||||
def cleanup_service(self) -> None:
|
def cleanup_service(self) -> None:
|
||||||
|
@ -21,9 +21,7 @@ class Memcached(Service):
|
|||||||
def prepare_service(self) -> None:
|
def prepare_service(self) -> None:
|
||||||
assert self.tests
|
assert self.tests
|
||||||
self.tests.install_dir(os.path.join("tmp", "sockets"))
|
self.tests.install_dir(os.path.join("tmp", "sockets"))
|
||||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
sock = self.bind_unix_socket(sockfile=self.sockfile)
|
||||||
sock.bind(os.path.relpath(self.sockfile))
|
|
||||||
sock.listen(8)
|
|
||||||
self.fork(*self.binary, inp=sock)
|
self.fork(*self.binary, inp=sock)
|
||||||
|
|
||||||
def cleanup_service(self) -> None:
|
def cleanup_service(self) -> None:
|
||||||
|
@ -20,9 +20,7 @@ class SCGI(Service):
|
|||||||
def prepare_service(self) -> None:
|
def prepare_service(self) -> None:
|
||||||
assert self.tests
|
assert self.tests
|
||||||
self.tests.install_dir(os.path.join("tmp", "sockets"))
|
self.tests.install_dir(os.path.join("tmp", "sockets"))
|
||||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
sock = self.bind_unix_socket(sockfile=self.sockfile)
|
||||||
sock.bind(os.path.relpath(self.sockfile))
|
|
||||||
sock.listen(8)
|
|
||||||
self.fork(*self.binary, inp=sock)
|
self.fork(*self.binary, inp=sock)
|
||||||
|
|
||||||
def cleanup_service(self) -> None:
|
def cleanup_service(self) -> None:
|
||||||
|
Loading…
Reference in New Issue
Block a user