# HG changeset patch # User Franz Glasner # Date 1742037638 -3600 # Node ID 6ff66311cfe5115e12e6623dd50b2912f9faf90b # Parent e18b5861868b2a35cfb954ae74c5da2ecd4cd1c1 Provide a uwsgi language plugin for PyPy2 also diff -r e18b5861868b -r 6ff66311cfe5 uwsginl-plugin-lang-pypy2/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uwsginl-plugin-lang-pypy2/Makefile Sat Mar 15 12:20:38 2025 +0100 @@ -0,0 +1,75 @@ +# Created by: Franz Glasner + +PORTNAME= ${UWSGI_NAME}-plugin-lang +PKGNAMESUFFIX= -${FLAVOR} +#DISTVERSION= 2.0.20 +PORTVERSION= 2.1.pl9.g${MYGH_TAG_DATE} +CATEGORIES= www python +# Use GitHub id for now (before official 2.1); see below +#MASTER_SITES= https://projects.unbit.it/downloads/ +#DISTNAME= uwsgi-${DISTVERSION} + +MAINTAINER= freebsd-dev@dom66.de +COMMENT= Language plugin for PyPy 2 +WWW= https://projects.unbit.it/uwsgi/ + +LICENSE= GPLv2-WITH-LINKING-EXCEPTION +LICENSE_GROUPS= FSF GPL OSI +LICENSE_NAME= GPLv2 with linking exception +LICENSE_FILE= ${WRKSRC}/LICENSE +LICENSE_PERMS= dist-mirror dist-sell pkg-mirror pkg-sell auto-accept + +FLAVORS= pypy2 +FLAVOR?= pypy2 + +BUILD_DEPENDS+= ${UWSGI_NAME}==${PORTVERSION}:www/uwsginl +BUILD_DEPENDS+= ${PYPY_PACKAGE}>=7:lang/${PYPY_PACKAGE} +RUN_DEPENDS+= ${UWSGI_NAME}==${PORTVERSION}:www/uwsginl +RUN_DEPENDS+= ${PYPY_PACKAGE}>=7:lang/${PYPY_PACKAGE} + +USES= cpe gettext-runtime pkgconfig +CPE_VENDOR= unbit + +.include "${.CURDIR}/../uwsginl/Makefile.gh" + +EXTRA_PATCHES= ${.CURDIR}/files/extra + +PLIST_FILES= ${PLUGIN_DIR}/${PLUGIN_FILENAME} + +.if ${FLAVOR} == pypy2 +PLUGIN_NAME= pypy2 +PYPY_PACKAGE= pypy2 +PYPY_EXECUTABLE= pypy2.7 +PYPY_LDLIBRARY= libpypy-c.so +PYPY_LIBDIR= lib-python/2.7 +.endif + +CFLAGS+= -DPYPY_LDLIBRARY="${PYPY_LDLIBRARY}" -DPYPY_LIBDIR="${PYPY_LIBDIR}" -DPYPY_PLUGIN_NAME="${PLUGIN_NAME}" + +MAKE_ENV+= UWSGI_PROFILE_OVERRIDE="plugin_build_dir=${STAGEDIR}${PREFIX}/${PLUGIN_DIR};plugin_dir=${PREFIX}/${PLUGIN_DIR}" PYTHON=${LOCALBASE}/bin/pypy3 + +DESCR= pkg-descr + +UWSGI_NAME= uwsginl +UWSGI_PATH= ${LOCALBASE}/bin/${UWSGI_NAME} +PLUGIN_DIR= lib/${UWSGI_NAME}/plugins + +# Where to find the sources for the plugin (defaults to plugins/${PLUGIN_NAME}) +PLUGIN_SOURCE= plugins/pypy +# The complete basename of the plugin +PLUGIN_FILENAME= ${PLUGIN_NAME}_plugin.so + +# Use the PATCHDIR of the binary executable by default +PATCHDIR?= ${.CURDIR}/../uwsginl/files + +do-configure: + @${DO_NADA} + +do-build: + @${MKDIR} ${STAGEDIR}${PREFIX}/${PLUGIN_DIR} + @(cd ${BUILD_WRKSRC}; ${SETENV} ${MAKE_ENV} ${UWSGI_PATH} --build-plugin "${PLUGIN_SOURCE} ${PLUGIN_NAME}") + +do-install: + ${INSTALL_LIB} ${BUILD_WRKSRC}/${PLUGIN_FILENAME} ${STAGEDIR}${PREFIX}/${PLUGIN_DIR} + +.include diff -r e18b5861868b -r 6ff66311cfe5 uwsginl-plugin-lang-pypy2/distinfo --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uwsginl-plugin-lang-pypy2/distinfo Sat Mar 15 12:20:38 2025 +0100 @@ -0,0 +1,3 @@ +TIMESTAMP = 1741948883 +SHA256 (unbit-uwsgi-2.1.pl9.g20241026-89cb161cda959697a4afe013f348b06646b960aa_GH0.tar.gz) = 957c6962655c3fdf81128ed2e39c42dd6eb1c3e426357e40594394e63c8935c0 +SIZE (unbit-uwsgi-2.1.pl9.g20241026-89cb161cda959697a4afe013f348b06646b960aa_GH0.tar.gz) = 866454 diff -r e18b5861868b -r 6ff66311cfe5 uwsginl-plugin-lang-pypy2/files/extra/patch-plugins_pypy_pypy__plugin.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uwsginl-plugin-lang-pypy2/files/extra/patch-plugins_pypy_pypy__plugin.c Sat Mar 15 12:20:38 2025 +0100 @@ -0,0 +1,166 @@ +--- plugins/pypy/pypy_plugin.c.orig 2024-10-26 11:39:02.000000000 +0200 ++++ plugins/pypy/pypy_plugin.c 2025-03-15 12:00:42.355380000 +0100 +@@ -9,6 +9,24 @@ + + #include + ++#if !defined(PYPY_PLUGIN_NAME) ++#error PYPY_PLUGIN_NAME not defined ++#endif ++#if !defined(PYPY_LDLIBRARY) ++#error PYPY_LDLIBRARY not defined ++#endif ++#if !defined(PYPY_LIBDIR) ++#error PYPY_LIBDIR not defined ++#endif ++ ++#define STR2(__x) #__x ++ ++#define STR(__x) STR2(__x) ++ ++#define CONCAT2(__x, __y) __x##__y ++ ++#define CONCAT(__x, __y) CONCAT2(__x, __y) ++ + struct uwsgi_pypy { + void *handler; + char *lib; +@@ -42,9 +60,10 @@ void (*uwsgi_pypy_post_fork_hook)(void); + void (*uwsgi_pypy_hook_pythonpath)(char *); + void (*uwsgi_pypy_hook_request)(void *, int); + void (*uwsgi_pypy_post_fork_hook)(void); ++void (*uwsgi_pypy_hook_atexit)(void); + + extern struct uwsgi_server uwsgi; +-struct uwsgi_plugin pypy_plugin; ++struct uwsgi_plugin CONCAT(PYPY_PLUGIN_NAME, _plugin); + + static int uwsgi_pypy_init() { + +@@ -58,7 +77,7 @@ static int uwsgi_pypy_init() { + } + + if (dlsym(RTLD_DEFAULT, "rpython_startup_code")) { +- uwsgi_log("PyPy runtime detected, skipping libpypy-c loading\n"); ++ uwsgi_log("PyPy runtime detected, skipping " STR(PYPY_LDLIBRARY) " loading\n"); + goto ready; + } + else if (upypy.lib) { +@@ -68,26 +87,26 @@ static int uwsgi_pypy_init() { + if (upypy.home) { + // first try with /bin way: + #ifdef __CYGWIN__ +- char *libpath = uwsgi_concat2(upypy.home, "/bin/libpypy-c.dll"); ++ char *libpath = uwsgi_concat2(upypy.home, "/bin/" STR(PYPY_LDLIBRARY)); + #elif defined(__APPLE__) +- char *libpath = uwsgi_concat2(upypy.home, "/bin/libpypy-c.dylib"); ++ char *libpath = uwsgi_concat2(upypy.home, "/bin/" STR(PYPY_LDLIBRARY)); + #else +- char *libpath = uwsgi_concat2(upypy.home, "/bin/libpypy-c.so"); ++ char *libpath = uwsgi_concat2(upypy.home, "/bin/" STR(PYPY_LDLIBRARY)); + #endif + if (uwsgi_file_exists(libpath)) { +- upypy.handler = dlopen(libpath, RTLD_NOW | RTLD_GLOBAL); +- } +- free(libpath); ++ upypy.handler = dlopen(libpath, RTLD_NOW | RTLD_GLOBAL); ++ } ++ free(libpath); + + // fallback to old-style way + if (!upypy.handler) { + + #ifdef __CYGWIN__ +- char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dll"); ++ char *libpath = uwsgi_concat2(upypy.home, "/" STR(PYPY_LDLIBRARY)); + #elif defined(__APPLE__) +- char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dylib"); ++ char *libpath = uwsgi_concat2(upypy.home, "/" STR(PYPY_LDLIBRARY)); + #else +- char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.so"); ++ char *libpath = uwsgi_concat2(upypy.home, "/" STR(PYPY_LDLIBRARY)); + #endif + if (uwsgi_file_exists(libpath)) { + upypy.handler = dlopen(libpath, RTLD_NOW | RTLD_GLOBAL); +@@ -98,11 +117,11 @@ static int uwsgi_pypy_init() { + // fallback to standard library search path + if (!upypy.handler) { + #ifdef __CYGWIN__ +- upypy.handler = dlopen("libpypy-c.dll", RTLD_NOW | RTLD_GLOBAL); ++ upypy.handler = dlopen(STR(PYPY_LDLIBRARY), RTLD_NOW | RTLD_GLOBAL); + #elif defined(__APPLE__) +- upypy.handler = dlopen("libpypy-c.dylib", RTLD_NOW | RTLD_GLOBAL); ++ upypy.handler = dlopen(STR(PYPY_LDLIBRARY), RTLD_NOW | RTLD_GLOBAL); + #else +- upypy.handler = dlopen("libpypy-c.so", RTLD_NOW | RTLD_GLOBAL); ++ upypy.handler = dlopen(STR(PYPY_LDLIBRARY), RTLD_NOW | RTLD_GLOBAL); + #endif + } + } +@@ -126,7 +145,7 @@ static int uwsgi_pypy_init() { + + u_pypy_init_threads = dlsym(upypy.handler, "pypy_init_threads"); + if (!u_pypy_init_threads) { +- uwsgi_log("!!! WARNING your libpypy-c does not export pypy_init_threads, multithreading will not work !!!\n"); ++ uwsgi_log("!!! WARNING your " STR(PYPY_LDLIBRARY) " does not export pypy_init_threads, multithreading will not work !!!\n"); + } + + u_rpython_startup_code(); +@@ -140,7 +159,7 @@ static int uwsgi_pypy_init() { + } + + if (u_pypy_setup_home(upypy.home, 0)) { +- char *retry = uwsgi_concat2(upypy.home, "/lib_pypy"); ++ char *retry = uwsgi_concat2(upypy.home, "/" STR(PYPY_LIBDIR)); + if (uwsgi_is_dir(retry)) { + // this time we use debug + if (!u_pypy_setup_home(retry, 1)) { +@@ -161,7 +180,7 @@ ready: + + u_pypy_thread_attach = dlsym(upypy.handler, "pypy_thread_attach"); + if (!u_pypy_thread_attach) { +- uwsgi_log("!!! WARNING your libpypy-c does not export pypy_thread_attach, multithreading will not work !!!\n"); ++ uwsgi_log("!!! WARNING your " STR(PYPY_LDLIBRARY) " does not export pypy_thread_attach, multithreading will not work !!!\n"); + } + + if (upypy.setup) { +@@ -266,13 +285,17 @@ static void uwsgi_pypy_init_apps() { + } + } + +-/* ++ + static void uwsgi_pypy_atexit() { +- if (pypy_debug_file) +- fflush(pypy_debug_file); ++ /* NOTE: this function is NOT called when "skip-atexit = true" is configured */ ++ if (!uwsgi_pypy_hook_atexit) { ++ uwsgi_log("!!! Your pypy setup does not define a uwsgi_pypy_atexit !!!\n"); ++ return; ++ } ++ uwsgi_pypy_hook_atexit(); + } +-*/ + ++ + static void uwsgi_opt_pypy_ini_paste(char *opt, char *value, void *foobar) { + uwsgi_opt_load_ini(opt, value, NULL); + upypy.paste = value; +@@ -372,8 +395,8 @@ static int uwsgi_pypy_mule(char *opt) { + } + + +-struct uwsgi_plugin pypy_plugin = { +- .name = "pypy", ++struct uwsgi_plugin CONCAT(PYPY_PLUGIN_NAME, _plugin) = { ++ .name = STR(PYPY_PLUGIN_NAME), + .modifier1 = 0, + .on_load = uwsgi_pypy_onload, + .init = uwsgi_pypy_init, +@@ -388,4 +411,6 @@ struct uwsgi_plugin pypy_plugin = { + .rpc = uwsgi_pypy_rpc, + .post_fork = uwsgi_pypy_post_fork, + .mule = uwsgi_pypy_mule, ++ ++ .atexit = uwsgi_pypy_atexit, + }; diff -r e18b5861868b -r 6ff66311cfe5 uwsginl-plugin-lang-pypy2/files/extra/patch-plugins_pypy_pypy__setup.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uwsginl-plugin-lang-pypy2/files/extra/patch-plugins_pypy_pypy__setup.py Sat Mar 15 12:20:38 2025 +0100 @@ -0,0 +1,209 @@ +--- plugins/pypy/pypy_setup.py.orig 2024-10-26 11:39:02.000000000 +0200 ++++ plugins/pypy/pypy_setup.py 2025-03-15 12:13:38.474221000 +0100 +@@ -31,6 +31,7 @@ + extern void (*uwsgi_pypy_hook_pythonpath)(char *); + extern void (*uwsgi_pypy_hook_request)(struct wsgi_request *); + extern void (*uwsgi_pypy_post_fork_hook)(void); ++extern void (*uwsgi_pypy_hook_atexit)(void); + ''' + + # here we load CFLAGS and uwsgi.h from the binary +@@ -48,8 +49,8 @@ + uwsgi_defines = [] + uwsgi_cflags = ffi.string(lib0.uwsgi_get_cflags()).split() + for cflag in uwsgi_cflags: +- if cflag.startswith(b'-D'): +- line = cflag[2:].decode() ++ if cflag.startswith('-D'): ++ line = cflag[2:] + if '=' in line: + (key, value) = line.split('=', 1) + uwsgi_cdef.append('#define %s ...' % key) +@@ -59,6 +60,12 @@ + uwsgi_defines.append('#define %s 1' % line) + uwsgi_dot_h = ffi.string(lib0.uwsgi_get_dot_h()) + ++# ++# Replace #include on FreeBSD because it is found on a non-standard ++# location for cffi. ++# ++uwsgi_dot_h = uwsgi_dot_h.replace('#include ', '#include "/usr/local/include/pcre.h"') ++ + # uwsgi definitions + cdefines = ''' + %s +@@ -110,6 +117,8 @@ + uint64_t running_time; + uint64_t avg_response_time; + uint64_t tx; ++ ++ int hijacked; + ...; + }; + +@@ -164,11 +173,14 @@ + struct wsgi_request *wsgi_req; + + struct uwsgi_plugin *p[]; ++ ++ int skip_atexit_teardown; ++ + ...; + }; + extern struct uwsgi_server uwsgi; + +-extern struct uwsgi_plugin pypy_plugin; ++extern struct uwsgi_plugin pypy2_plugin; + + extern const char *uwsgi_pypy_version; + +@@ -269,9 +281,9 @@ + %s + + extern struct uwsgi_server uwsgi; +-extern struct uwsgi_plugin pypy_plugin; ++extern struct uwsgi_plugin pypy2_plugin; + %s +-''' % ('\n'.join(uwsgi_defines), uwsgi_dot_h.decode(), hooks) ++''' % ('\n'.join(uwsgi_defines), uwsgi_dot_h, hooks) + + ffi.cdef(cdefines) + lib = ffi.verify(cverify) +@@ -286,7 +298,7 @@ + + # fix argv if needed + if len(sys.argv) == 0: +- sys.argv.insert(0, ffi.string(lib.uwsgi_binary_path()).decode()) ++ sys.argv.insert(0, ffi.string(lib.uwsgi_binary_path())) + + + @ffi.callback("void(char *)") +@@ -305,7 +317,7 @@ + load a wsgi module + """ + global wsgi_application +- m = ffi.string(module).decode() ++ m = ffi.string(module) + c = 'application' + if ':' in m: + m, c = m.split(':') +@@ -324,7 +336,7 @@ + global wsgi_application + w = ffi.string(filename) + c = 'application' +- mod = imp.load_source('uwsgi_file_wsgi', w.decode()) ++ mod = imp.load_source('uwsgi_file_wsgi', w) + wsgi_application = getattr(mod, c) + + +@@ -334,7 +346,7 @@ + load a .ini paste app + """ + global wsgi_application +- c = ffi.string(config).decode() ++ c = ffi.string(config) + if c.startswith('config:'): + c = c[7:] + if c[0] != '/': +@@ -363,11 +375,46 @@ + """ + add an item to the pythonpath + """ +- path = ffi.string(item).decode() ++ path = ffi.string(item) + sys.path.append(path) + print("added %s to pythonpath" % path) + + ++@ffi.callback("void()") ++def uwsgi_pypy_atexit(): ++ """ ++ .atexit handler implementation ++ ++ Modelled after python_plugin.c ++ """ ++ mywid = lib.uwsgi.mywid ++ if mywid > 0: ++ # if hijacked do not run atexit hooks ++ if lib.uwsgi.workers[mywid].hijacked: ++ return ++ # if busy do not run atexit hooks ++ if lib.uwsgi_worker_is_busy(mywid): ++ return ++ # managing atexit in async mode is a real pain...skip it for now ++ if getattr(lib.uwsgi, "async") > 0: ++ return ++ ++ import uwsgi ++ uahandler = getattr(uwsgi, "atexit", None) ++ if callable(uahandler): ++ uahandler() ++ ++ if lib.uwsgi.skip_atexit_teardown: ++ return ++ ++ import atexit ++ aefn = getattr(atexit, "_run_exitfuncs", None) ++ if callable(aefn): ++ aefn() ++ else: ++ print("!!! atexit._run_exitfuncs() not found !!!") ++ ++ + class WSGIfilewrapper(object): + """ + class implementing wsgi.file_wrapper +@@ -470,17 +517,15 @@ + def start_response(status, headers, exc_info=None): + if exc_info: + traceback.print_exception(*exc_info) +- status = status.encode() + lib.uwsgi_response_prepare_headers(wsgi_req, ffi.new("char[]", status), len(status)) + for hh in headers: +- hh = (hh[0].encode(), hh[1].encode()) + lib.uwsgi_response_add_header(wsgi_req, ffi.new("char[]", hh[0]), len(hh[0]), ffi.new("char[]", hh[1]), len(hh[1])) + return writer + + environ = {} + iov = wsgi_req.hvec + for i in range(0, wsgi_req.var_cnt, 2): +- environ[ffi.string(ffi.cast("char*", iov[i].iov_base), iov[i].iov_len).decode()] = ffi.string(ffi.cast("char*", iov[i+1].iov_base), iov[i+1].iov_len).decode() ++ environ[ffi.string(ffi.cast("char*", iov[i].iov_base), iov[i].iov_len)] = ffi.string(ffi.cast("char*", iov[i+1].iov_base), iov[i+1].iov_len) + + environ['wsgi.version'] = (1, 0) + scheme = 'http' +@@ -525,6 +570,7 @@ + lib.uwsgi_pypy_hook_pythonpath = uwsgi_pypy_pythonpath + lib.uwsgi_pypy_hook_request = uwsgi_pypy_wsgi_handler + lib.uwsgi_pypy_post_fork_hook = uwsgi_pypy_post_fork_hook ++lib.uwsgi_pypy_hook_atexit = uwsgi_pypy_atexit + + """ + Here we define the "uwsgi" virtual module +@@ -539,7 +585,7 @@ + def uwsgi_pypy_uwsgi_register_signal(signum, kind, handler): + cb = ffi.callback('void(int)', handler) + uwsgi_gc.append(cb) +- if lib.uwsgi_register_signal(signum, ffi.new("char[]", kind), cb, lib.pypy_plugin.modifier1) < 0: ++ if lib.uwsgi_register_signal(signum, ffi.new("char[]", kind), cb, lib.pypy2_plugin.modifier1) < 0: + raise Exception("unable to register signal %d" % signum) + uwsgi.register_signal = uwsgi_pypy_uwsgi_register_signal + +@@ -564,7 +610,7 @@ + rpc_func = uwsgi_pypy_RPC(func) + cb = ffi.callback("int(int, char*[], int[], char**)", rpc_func) + uwsgi_gc.append(cb) +- if lib.uwsgi_register_rpc(ffi.new("char[]", name), ffi.addressof(lib.pypy_plugin), argc, cb) < 0: ++ if lib.uwsgi_register_rpc(ffi.new("char[]", name), ffi.addressof(lib.pypy2_plugin), argc, cb) < 0: + raise Exception("unable to register rpc func %s" % name) + uwsgi.register_rpc = uwsgi_pypy_uwsgi_register_rpc + +@@ -1069,7 +1115,7 @@ + + + def uwsgi_pypy_setup_continulets(): +- if lib.uwsgi["async"] < 1: ++ if getattr(lib.uwsgi, "async") < 1: + raise Exception("pypy continulets require async mode !!!") + lib.uwsgi.schedule_to_main = uwsgi_pypy_continulet_switch + lib.uwsgi.schedule_to_req = uwsgi_pypy_continulet_schedule diff -r e18b5861868b -r 6ff66311cfe5 uwsginl-plugin-lang-pypy2/misc/make-extra-patches.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uwsginl-plugin-lang-pypy2/misc/make-extra-patches.sh Sat Mar 15 12:20:38 2025 +0100 @@ -0,0 +1,5 @@ +#!/bin/sh + +diff -u --show-c-function plugins/pypy/pypy_plugin.c.orig plugins/pypy/pypy_plugin.c >../../files/extra/patch-plugins_pypy_pypy__plugin.c + +diff -u plugins/pypy/pypy_setup.py.orig plugins/pypy/pypy_setup.py >../../files/extra/patch-plugins_pypy_pypy__setup.py diff -r e18b5861868b -r 6ff66311cfe5 uwsginl-plugin-lang-pypy2/pkg-descr --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uwsginl-plugin-lang-pypy2/pkg-descr Sat Mar 15 12:20:38 2025 +0100 @@ -0,0 +1,3 @@ +PyPy2 language plugin for uwsginl. +Dynamically links to PyPy2's libpypy-c.so. +Contains a PY2 compatible pypy_setup.py again.