Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backports for 2.0.28 #2690

Merged
merged 4 commits into from
Oct 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ jobs:
sudo apt install --no-install-recommends -qqyf \
libpcre2-dev libjansson-dev libcap2-dev \
php-dev libphp-embed libargon2-dev libsodium-dev \
pypy3
pypy3 default-jdk-headless libperl-dev \
ruby-dev ruby-rack
- uses: actions/checkout@v4
- name: Set env
run: echo "PROFILE=integration-tests" >> $GITHUB_ENV
Expand Down
2 changes: 1 addition & 1 deletion PKG-INFO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: uWSGI
Version: 2.0.27
Version: 2.0.28
Summary: The uWSGI server
Home-page: https://uwsgi-docs.readthedocs.io/en/latest/
Author: Unbit
Expand Down
2 changes: 1 addition & 1 deletion buildconf/integration-tests.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[uwsgi]
inherit = base
main_plugin =
plugins = python,php,pypy
plugins = notfound,python,php,pypy,jvm,jwsgi,psgi,cgi,rack
6 changes: 0 additions & 6 deletions core/master_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,6 @@ void uwsgi_destroy_processes() {

uwsgi_detach_daemons();

for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0) {
waitpid(uwsgi.workers[i].pid, &waitpid_status, 0);
}
}

for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways[i].pid > 0) {
kill(ushared->gateways[i].pid, SIGKILL);
Expand Down
10 changes: 9 additions & 1 deletion core/uwsgi.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"procname-master", required_argument, 0, "set master process name", uwsgi_opt_set_str, &uwsgi.procname_master, UWSGI_OPT_PROCNAME},

{"single-interpreter", no_argument, 'i', "do not use multiple interpreters (where available)", uwsgi_opt_true, &uwsgi.single_interpreter, 0},
{"need-app", no_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0},
{"need-app", optional_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0},
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
{"honour-stdin", no_argument, 0, "do not remap stdin to /dev/null", uwsgi_opt_true, &uwsgi.honour_stdin, 0},
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
Expand Down Expand Up @@ -1319,6 +1319,8 @@ void kill_them_all(int signum) {
// gracefully destroy
void gracefully_kill_them_all(int signum) {

int waitpid_status;

if (uwsgi_instance_is_dying) return;
uwsgi.status.gracefully_destroying = 1;

Expand All @@ -1341,6 +1343,12 @@ void gracefully_kill_them_all(int signum) {
}
}

for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0) {
waitpid(uwsgi.workers[i].pid, &waitpid_status, 0);
}
}

uwsgi_destroy_processes();
}

Expand Down
21 changes: 13 additions & 8 deletions plugins/python/uwsgiplugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def get_python_version():
if not 'UWSGI_PYTHON_NOLIB' in os.environ:
LIBS = sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
# check if it is a non-shared build (but please, add --enable-shared to your python's ./configure script)
if not sysconfig.get_config_var('Py_ENABLE_SHARED'):
use_static_lib = not sysconfig.get_config_var('Py_ENABLE_SHARED')
if use_static_lib:
libdir = sysconfig.get_config_var('LIBPL')
# libdir does not exists, try to get it from the venv
version = get_python_version()
Expand Down Expand Up @@ -75,13 +76,17 @@ def get_python_version():
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LIBRARY'))
if not os.path.exists(libpath):
libpath = '%s/libpython%s.a' % (libdir, version)
LIBS.append(libpath)
# hack for messy linkers/compilers
if '-lutil' in LIBS:
LIBS.append('-lutil')
if '-lrt' in LIBS:
LIBS.append('-lrt')
else:

if os.path.exists(libpath):
LIBS.append(libpath)
# hack for messy linkers/compilers
if '-lutil' in LIBS:
LIBS.append('-lutil')
if '-lrt' in LIBS:
LIBS.append('-lrt')
else:
use_static_lib = False
if not use_static_lib:
try:
libdir = sysconfig.get_config_var('LIBDIR')
except:
Expand Down
6 changes: 6 additions & 0 deletions t/cgi/hello.cgi
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh

echo "Content-Type: text/plain"
echo
echo "Hello world!"
echo "PATH_INFO=${PATH_INFO}"
2 changes: 1 addition & 1 deletion t/php/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ cache2 = name=session,items=1000,store=/tmp/uwsgi-session-cache,bitmap=1
php-set = session.save_handler=uwsgi
php-set = session.save_path=session

php-docroot = t/php/
php-docroot = %d
4 changes: 0 additions & 4 deletions t/python/manage_script_name/manage_script_name_test.ini
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
[uwsgi]
http-socket = :8080

master = 1

; Three apps on three mountpoints
wsgi-file = %d/useless_app.py

Expand Down
59 changes: 0 additions & 59 deletions t/python/manage_script_name/test_manage_script_name.py

This file was deleted.

2 changes: 1 addition & 1 deletion t/python/manage_script_name/useless_app.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return env['SCRIPT_NAME']
return [env['SCRIPT_NAME'].encode('ascii'), ]
9 changes: 9 additions & 0 deletions t/rack/app.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class App

def call(environ)
[200, {'Content-Type' => 'text/html'}, ['Hello']]
end

end

run App.new
142 changes: 128 additions & 14 deletions t/runner
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import unittest

TESTS_DIR = os.path.dirname(__file__)
UWSGI_BINARY = os.getenv("UWSGI_BINARY", os.path.join(TESTS_DIR, "..", "uwsgi"))
UWSGI_PLUGINS = os.getenv("UWSGI_PLUGINS", "all").split(" ")
UWSGI_PLUGINS = os.getenv("UWSGI_PLUGINS_TEST", "all").split(" ")
UWSGI_ADDR = "127.0.0.1"
UWSGI_PORT = 8000
UWSGI_HTTP = f"{UWSGI_ADDR}:{UWSGI_PORT}"
Expand Down Expand Up @@ -83,26 +83,68 @@ class UwsgiTest(unittest.TestCase):
result = self._outcome.result
ok = not (result.errors + result.failures)

self.testserver.send_signal(signal.SIGTERM)
if not ok:
print(self.testserver.stdout.read(), file=sys.stderr)
if hasattr(self, "testserver"):
self.testserver.send_signal(signal.SIGTERM)
if not ok:
print(self.testserver.stdout.read(), file=sys.stderr)

self.testserver.wait()
self.testserver.stdout.close()
self.testserver.wait()
self.testserver.stdout.close()

def assert_GET_body(self, url_path, body_expected):
with requests.get(f"http://{UWSGI_HTTP}{url_path}") as r:
self.assertEqual(r.text, body_expected)

@unittest.skipUnless(*plugins_available(["python"]))
def test_static_expires(self):
self.start_listen_server(
[
"--plugin",
"python", # provide a request plugin
"notfound",
os.path.join(TESTS_DIR, "static", "config.ini"),
]
)

with requests.get(f"http://{UWSGI_HTTP}/foobar/config.ini") as r:
self.assertTrue("Expires" in r.headers)

@unittest.skipUnless(*plugins_available(["python"]))
def test_mountpoints(self):
self.start_listen_server(
[
"--plugin",
"python",
os.path.join(
TESTS_DIR,
"python",
"manage_script_name",
"manage_script_name_test.ini",
),
]
)

mps = {"/foo", "/foobis/", "/footris/"}

for mp in mps:
# Requests to /foo should kick-in the managed script name.
self.assert_GET_body(mp, mp)

ends = mp.endswith("/")

# And equally requests to /foo/
self.assert_GET_body(f"{mp}/" if not ends else f"{mp}"[:-1], mp)

# Or correct requests (/foo/resource)
self.assert_GET_body(f"{mp}/resource" if not ends else f"{mp}resource", mp)

mps = {
"/fooanything",
"/foobisis/",
"/foofighters",
}

for mp in mps:
self.assert_GET_body(mp, "")

@unittest.skipUnless(*plugins_available(["python"]))
def test_python3_helloworld(self):
self.start_listen_server(
Expand All @@ -114,8 +156,7 @@ class UwsgiTest(unittest.TestCase):
]
)

with requests.get(f"http://{UWSGI_HTTP}/") as r:
self.assertEqual(r.text, "Hello World")
self.assert_GET_body("/", "Hello World")

@unittest.skipUnless(*plugins_available(["pypy"]))
def test_pypy3_helloworld(self):
Expand All @@ -125,8 +166,7 @@ class UwsgiTest(unittest.TestCase):
]
)

with requests.get(f"http://{UWSGI_HTTP}/") as r:
self.assertEqual(r.text, "Hello World")
self.assert_GET_body("/", "Hello World")

@unittest.skipUnless(*plugins_available(["php"]))
def test_php_session(self):
Expand All @@ -136,8 +176,82 @@ class UwsgiTest(unittest.TestCase):
]
)

with requests.get(f"http://{UWSGI_HTTP}/test.php") as r:
self.assertEqual(r.text, "PASS\n")
self.assert_GET_body("/test.php", "PASS\n")

@unittest.skipUnless(*plugins_available(["jvm"]))
def test_jvm_hellworld(self):
classpath = ":".join(
[
"/usr/share/java/uwsgi.jar",
os.path.join(TESTS_DIR, "java"),
os.path.join(TESTS_DIR, "..", "plugins", "jvm"),
]
)

subprocess.call(
[
"javac",
"-classpath",
classpath,
os.path.join(TESTS_DIR, "java", "rpc.java"),
]
)

self.start_listen_server(
[
"--need-app=0",
"--plugins",
"0:jvm,jwsgi",
"--jvm-classpath",
classpath,
"--jwsgi",
"rpc:application",
]
)

self.assert_GET_body("/", "<h1>null</h1>")

@unittest.skipUnless(*plugins_available(["psgi"]))
def test_psgi_helloworld(self):
self.start_listen_server(
[
"--plugins",
"psgi",
"--psgi",
os.path.join(TESTS_DIR, "perl", "test_hello.psgi"),
]
)

self.assert_GET_body("/", "Hello, world!")

@unittest.skipUnless(*plugins_available(["cgi"]))
def test_cgi_helloworld(self):
self.start_listen_server(
[
"--need-app=0",
"--plugins",
"0:cgi",
"--cgi",
os.path.join(TESTS_DIR, "cgi", "hello.cgi"),
]
)

self.assert_GET_body(
"/foobar/say_hello", "Hello world!\nPATH_INFO=/foobar/say_hello\n"
)

@unittest.skipUnless(*plugins_available(["rack"]))
def test_rack_helloworld(self):
self.start_listen_server(
[
"--plugins",
"0:rack",
"--rack",
os.path.join(TESTS_DIR, "rack", "app.ru"),
]
)

self.assert_GET_body("/", "Hello")


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion t/static/config.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[uwsgi]
need-app = False
static-map = /foobar=t/static
static-map = /foobar=%d
static-expires-uri = ^/foobar/ 315360000
Loading