Description: fix php and pypy tests
 fixes the php (missing file)
 .
 fixes the pypy (inconsistent API for set_user_harakiri())
Author: Alexandre Rossi <niol@zincube.net>
Bug: https://github.com/unbit/uwsgi/pull/2691
Last-Update: 2025-03-02
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- a/Makefile
+++ b/Makefile
@@ -22,3 +22,5 @@
 
 %:
 	$(PYTHON) uwsgiconfig.py --build $@
+
+.PHONY: all clean check tests
--- a/plugins/pypy/pypy_setup.py
+++ b/plugins/pypy/pypy_setup.py
@@ -24,13 +24,13 @@
 ssize_t write(int, const void *, size_t);
 int close(int);
 
-void (*uwsgi_pypy_hook_execute_source)(char *);
-void (*uwsgi_pypy_hook_loader)(char *);
-void (*uwsgi_pypy_hook_file_loader)(char *);
-void (*uwsgi_pypy_hook_paste_loader)(char *);
-void (*uwsgi_pypy_hook_pythonpath)(char *);
-void (*uwsgi_pypy_hook_request)(struct wsgi_request *);
-void (*uwsgi_pypy_post_fork_hook)(void);
+extern void (*uwsgi_pypy_hook_execute_source)(char *);
+extern void (*uwsgi_pypy_hook_loader)(char *);
+extern void (*uwsgi_pypy_hook_file_loader)(char *);
+extern void (*uwsgi_pypy_hook_paste_loader)(char *);
+extern void (*uwsgi_pypy_hook_pythonpath)(char *);
+extern void (*uwsgi_pypy_hook_request)(struct wsgi_request *);
+extern void (*uwsgi_pypy_post_fork_hook)(void);
 '''
 
 # here we load CFLAGS and uwsgi.h from the binary
@@ -53,7 +53,7 @@
         if '=' in line:
             (key, value) = line.split('=', 1)
             uwsgi_cdef.append('#define %s ...' % key)
-            uwsgi_defines.append('#define %s %s' % (key, value.replace('\\"','"').replace('""','"')))
+            uwsgi_defines.append('#define %s %s' % (key, value.replace('\\"', '"').replace('""', '"')))
         else:
             uwsgi_cdef.append('#define %s ...' % line)
             uwsgi_defines.append('#define %s 1' % line)
@@ -64,107 +64,107 @@
 %s
 
 struct iovec {
-	void *iov_base;
-	size_t iov_len;
-	...;
+        void *iov_base;
+        size_t iov_len;
+        ...;
 };
 
 struct uwsgi_header {
-	uint8_t modifier1;
-	...;
+        uint8_t modifier1;
+        ...;
 };
 
 struct wsgi_request {
-	int fd;
-	int async_id;
-	uint16_t var_cnt;
-	struct iovec *hvec;
+        int fd;
+        int async_id;
+        uint16_t var_cnt;
+        struct iovec *hvec;
 
-	int async_ready_fd;
-	int async_last_ready_fd;
+        int async_ready_fd;
+        int async_last_ready_fd;
 
-	int suspended;
+        int suspended;
 
-	struct uwsgi_header *uh;
-	...;
+        struct uwsgi_header *uh;
+        ...;
 };
 
 struct uwsgi_opt {
-	char *key;
-	char *value;
-	...;
+        char *key;
+        char *value;
+        ...;
 };
 
 struct uwsgi_worker {
-	int id;
-	int pid;
-	uint64_t requests;
-	uint64_t delta_requests;
-	uint64_t signals;
-
-	int cheaped;
-	int suspended;
-	int sig;
-	uint8_t signum;
-
-	uint64_t running_time;
-	uint64_t avg_response_time;
-	uint64_t tx;
-	...;
+        int id;
+        int pid;
+        uint64_t requests;
+        uint64_t delta_requests;
+        uint64_t signals;
+
+        int cheaped;
+        int suspended;
+        int sig;
+        uint8_t signum;
+
+        uint64_t running_time;
+        uint64_t avg_response_time;
+        uint64_t tx;
+        ...;
 };
 
 struct uwsgi_plugin {
-	uint8_t modifier1;
+        uint8_t modifier1;
 
-	void (*suspend) (struct wsgi_request *);
+        void (*suspend) (struct wsgi_request *);
         void (*resume) (struct wsgi_request *);
-	...;
+        ...;
 };
 
 struct uwsgi_buffer {
-	char *buf;
-	size_t pos;
-	...;
+        char *buf;
+        size_t pos;
+        ...;
 };
 
 struct uwsgi_lock_item {
-	...;
+        ...;
 };
 
 struct uwsgi_cache {
-	struct uwsgi_lock_item *lock;
-	...;
+        struct uwsgi_lock_item *lock;
+        ...;
 };
 
 struct uwsgi_cache_item {
-	uint64_t keysize;
-	...;
+        uint64_t keysize;
+        ...;
 };
 
 struct uwsgi_server {
-	char hostname[];
-	int mywid;
-	int muleid;
-	int master_process;
+        char hostname[];
+        int mywid;
+        int muleid;
+        int master_process;
 
-	struct uwsgi_opt **exported_opts;
-	int exported_opts_cnt;	
+        struct uwsgi_opt **exported_opts;
+        int exported_opts_cnt;
 
-	struct uwsgi_worker *workers;
+        struct uwsgi_worker *workers;
 
-	int signal_socket;
-	int numproc;
-	int async;
+        int signal_socket;
+        int numproc;
+        int async;
 
-	void (*schedule_to_main) (struct wsgi_request *);
+        void (*schedule_to_main) (struct wsgi_request *);
         void (*schedule_to_req) (void);
 
-	struct wsgi_request *(*current_wsgi_req) (void);
-	
-	struct wsgi_request *wsgi_req;
+        struct wsgi_request *(*current_wsgi_req) (void);
 
-	struct uwsgi_plugin *p[];
-	...;
+        struct wsgi_request *wsgi_req;
+
+        struct uwsgi_plugin *p[];
+        ...;
 };
 extern struct uwsgi_server uwsgi;
 
@@ -248,7 +248,7 @@
 
 int uwsgi_ready_fd(struct wsgi_request *);
 
-void set_user_harakiri(struct wsgi_request *, int);
+void set_user_harakiri(int);
 
 int uwsgi_metric_set(char *, char *, int64_t);
 int uwsgi_metric_inc(char *, char *, int64_t);
@@ -288,20 +288,22 @@
 if len(sys.argv) == 0:
     sys.argv.insert(0, ffi.string(lib.uwsgi_binary_path()).decode())
 
-"""
-execute source, we expose it as cffi callback to avoid deadlocks
-after GIL initialization
-"""
+
 @ffi.callback("void(char *)")
 def uwsgi_pypy_execute_source(s):
+    """
+    execute source, we expose it as cffi callback to avoid deadlocks
+    after GIL initialization
+    """
     source = ffi.string(s)
     exec(source)
 
-"""
-load a wsgi module
-"""
+
 @ffi.callback("void(char *)")
 def uwsgi_pypy_loader(module):
+    """
+    load a wsgi module
+    """
     global wsgi_application
     m = ffi.string(module).decode()
     c = 'application'
@@ -313,22 +315,24 @@
         mod = __import__(m)
     wsgi_application = getattr(mod, c)
 
-"""
-load a mod_wsgi compliant .wsgi file
-"""
+
 @ffi.callback("void(char *)")
 def uwsgi_pypy_file_loader(filename):
+    """
+    load a mod_wsgi compliant .wsgi file
+    """
     global wsgi_application
     w = ffi.string(filename)
     c = 'application'
     mod = imp.load_source('uwsgi_file_wsgi', w.decode())
     wsgi_application = getattr(mod, c)
 
-"""
-load a .ini paste app
-"""
+
 @ffi.callback("void(char *)")
 def uwsgi_pypy_paste_loader(config):
+    """
+    load a .ini paste app
+    """
     global wsgi_application
     c = ffi.string(config).decode()
     if c.startswith('config:'):
@@ -343,29 +347,31 @@
     from paste.deploy import loadapp
     wsgi_application = loadapp('config:%s' % c)
 
-"""
-.post_fork_hook
-"""
+
 @ffi.callback("void()")
 def uwsgi_pypy_post_fork_hook():
+    """
+    .post_fork_hook
+    """
     import uwsgi
     if hasattr(uwsgi, 'post_fork_hook'):
         uwsgi.post_fork_hook()
 
-"""
-add an item to the pythonpath
-"""
+
 @ffi.callback("void(char *)")
 def uwsgi_pypy_pythonpath(item):
+    """
+    add an item to the pythonpath
+    """
     path = ffi.string(item).decode()
     sys.path.append(path)
     print("added %s to pythonpath" % path)
 
 
-"""
-class implementing wsgi.file_wrapper
-"""
 class WSGIfilewrapper(object):
+    """
+    class implementing wsgi.file_wrapper
+    """
     def __init__(self, wsgi_req, f, chunksize=0):
         self.wsgi_req = wsgi_req
         self.f = f
@@ -376,6 +382,17 @@
     def __iter__(self):
         return self
 
+    def __next__(self):
+        if self.chunksize:
+            data = self.f.read(self.chunksize)
+        else:
+            data = self.f.read()
+        if data:
+            return data
+        raise StopIteration()
+
+    next = __next__
+
     def sendfile(self):
         if hasattr(self.f, 'fileno'):
             lib.uwsgi_response_sendfile_do_can_close(self.wsgi_req, self.f.fileno(), 0, 0, 0)
@@ -392,10 +409,10 @@
                 lib.uwsgi_response_write_body_do(self.wsgi_req, ffi.new("char[]", chunk), len(chunk))
 
 
-"""
-class implementing wsgi.input
-"""
 class WSGIinput(object):
+    """
+    class implementing wsgi.input
+    """
     def __init__(self, wsgi_req):
         self.wsgi_req = wsgi_req
 
@@ -439,11 +456,11 @@
         return chunk
 
 
-"""
-the WSGI request handler
-"""
 @ffi.callback("void(struct wsgi_request *)")
 def uwsgi_pypy_wsgi_handler(wsgi_req):
+    """
+    the WSGI request handler
+    """
     import uwsgi
     global wsgi_application
 
@@ -518,6 +535,7 @@
 uwsgi.version = ffi.string(lib.uwsgi_pypy_version)
 uwsgi.hostname = ffi.string(lib.uwsgi.hostname)
 
+
 def uwsgi_pypy_uwsgi_register_signal(signum, kind, handler):
     cb = ffi.callback('void(int)', handler)
     uwsgi_gc.append(cb)
@@ -550,6 +568,7 @@
         raise Exception("unable to register rpc func %s" % name)
 uwsgi.register_rpc = uwsgi_pypy_uwsgi_register_rpc
 
+
 def uwsgi_pypy_rpc(node, func, *args):
     argc = 0
     argv = ffi.new('char*[256]')
@@ -570,7 +589,7 @@
     else:
         c_node = ffi.NULL
 
-    response = lib.uwsgi_do_rpc(c_node, ffi.new("char[]",func), argc, argv, argvs, rsize)
+    response = lib.uwsgi_do_rpc(c_node, ffi.new("char[]", func), argc, argv, argvs, rsize)
     if response:
         ret = ffi.buffer(response, rsize[0])[:]
         lib.free(response)
@@ -578,13 +597,14 @@
     return None
 uwsgi.rpc = uwsgi_pypy_rpc
 
+
 def uwsgi_pypy_call(func, *args):
     node = None
     if b'@' in func:
         (func, node) = func.split(b'@')
     return uwsgi_pypy_rpc(node, func, *args)
 uwsgi.call = uwsgi_pypy_call
-    
+
 uwsgi.signal = lambda x: lib.uwsgi_signal_send(lib.uwsgi.signal_socket, x)
 
 uwsgi.metric_get = lambda x: lib.uwsgi_metric_get(x, ffi.NULL)
@@ -594,6 +614,7 @@
 uwsgi.metric_mul = lambda x, y=1: lib.uwsgi_metric_mul(x, ffi.NULL, y)
 uwsgi.metric_div = lambda x, y=1: lib.uwsgi_metric_div(x, ffi.NULL, y)
 
+
 def uwsgi_pypy_uwsgi_cache_get(key, cache=ffi.NULL):
     vallen = ffi.new('uint64_t*')
     value = lib.uwsgi_cache_magic_get(key, len(key), vallen, ffi.NULL, cache)
@@ -604,21 +625,25 @@
     return ret
 uwsgi.cache_get = uwsgi_pypy_uwsgi_cache_get
 
+
 def uwsgi_pypy_uwsgi_cache_set(key, value, expires=0, cache=ffi.NULL):
     if lib.uwsgi_cache_magic_set(key, len(key), value, len(value), expires, 0, cache) < 0:
         raise Exception('unable to store item in the cache')
 uwsgi.cache_set = uwsgi_pypy_uwsgi_cache_set
 
+
 def uwsgi_pypy_uwsgi_cache_update(key, value, expires=0, cache=ffi.NULL):
     if lib.uwsgi_cache_magic_set(key, len(key), value, len(value), expires, 1 << 1, cache) < 0:
         raise Exception('unable to store item in the cache')
 uwsgi.cache_update = uwsgi_pypy_uwsgi_cache_update
 
+
 def uwsgi_pypy_uwsgi_cache_del(key, cache=ffi.NULL):
     if lib.uwsgi_cache_magic_del(key, len(key), cache) < 0:
         raise Exception('unable to delete item from the cache')
 uwsgi.cache_del = uwsgi_pypy_uwsgi_cache_del
 
+
 def uwsgi_pypy_uwsgi_cache_keys(cache=ffi.NULL):
     uc = lib.uwsgi_cache_by_name(cache)
     if uc == ffi.NULL:
@@ -636,11 +661,13 @@
     return l
 uwsgi.cache_keys = uwsgi_pypy_uwsgi_cache_keys
 
+
 def uwsgi_pypy_uwsgi_add_timer(signum, secs):
     if lib.uwsgi_add_timer(signum, secs) < 0:
         raise Exception("unable to register timer")
 uwsgi.add_timer = uwsgi_pypy_uwsgi_add_timer
 
+
 def uwsgi_pypy_uwsgi_add_rb_timer(signum, secs):
     if lib.uwsgi_signal_add_rb_timer(signum, secs, 0) < 0:
         raise Exception("unable to register redblack timer")
@@ -652,16 +679,19 @@
         raise Exception("unable to register file monitor")
 uwsgi.add_file_monitor = uwsgi_pypy_uwsgi_add_file_monitor
 
+
 def uwsgi_pypy_lock(num=0):
     if lib.uwsgi_user_lock(num) < 0:
         raise Exception("invalid lock")
 uwsgi.lock = uwsgi_pypy_lock
 
+
 def uwsgi_pypy_unlock(num=0):
     if lib.uwsgi_user_unlock(num) < 0:
         raise Exception("invalid lock")
 uwsgi.unlock = uwsgi_pypy_unlock
 
+
 def uwsgi_pypy_masterpid():
     if lib.uwsgi.master_process:
         return lib.uwsgi.workers[0].pid
@@ -672,18 +702,21 @@
 
 uwsgi.mule_id = lambda: lib.uwsgi.muleid
 
+
 def uwsgi_pypy_signal_registered(signum):
     if lib.uwsgi_signal_registered(signum) > 0:
         return True
     return False
 uwsgi.signal_registered = uwsgi_pypy_signal_registered
 
+
 def uwsgi_pypy_alarm(alarm, msg):
     lib.uwsgi_alarm_trigger(ffi.new('char[]', alarm), ffi.new('char[]', msg), len(msg))
 uwsgi.alarm = uwsgi_pypy_alarm
 
 uwsgi.setprocname = lambda name: lib.uwsgi_set_processname(ffi.new('char[]', name))
 
+
 def uwsgi_pypy_add_cron(signum, minute, hour, day, month, week):
     if lib.uwsgi_signal_add_cron(signum, minute, hour, day, month, week) < 0:
         raise Exception("unable to register cron")
@@ -708,25 +741,28 @@
     else:
         uwsgi.opt[k] = v
 
+
 def uwsgi_pypy_current_wsgi_req():
     wsgi_req = lib.uwsgi.current_wsgi_req()
     if wsgi_req == ffi.NULL:
         raise Exception("unable to get current wsgi_request, check your setup !!!")
     return wsgi_req
 
-"""
-uwsgi.suspend()
-"""
+
 def uwsgi_pypy_suspend():
+    """
+    uwsgi.suspend()
+    """
     wsgi_req = uwsgi_pypy_current_wsgi_req()
     if lib.uwsgi.schedule_to_main:
         lib.uwsgi.schedule_to_main(wsgi_req)
 uwsgi.suspend = uwsgi_pypy_suspend
 
-"""
-uwsgi.workers()
-"""
+
 def uwsgi_pypy_workers():
+    """
+    uwsgi.workers()
+    """
     workers = []
     for i in range(1, lib.uwsgi.numproc+1):
         worker = {}
@@ -745,31 +781,33 @@
             if lib.uwsgi.workers[i].sig:
                 worker['status'] = 'sig%d' % lib.uwsgi.workers[i].signum
             elif lib.uwsgi_worker_is_busy(i):
-                worker['status'] = 'busy' 
+                worker['status'] = 'busy'
             else:
                 worker['status'] = 'idle'
         worker['running_time'] = lib.uwsgi.workers[i].running_time
         worker['avg_rt'] = lib.uwsgi.workers[i].avg_response_time
         worker['tx'] = lib.uwsgi.workers[i].tx
-            
+
         workers.append(worker)
     return workers
-    
+
 uwsgi.workers = uwsgi_pypy_workers
 
-"""
-uwsgi.async_sleep(timeout)
-"""
+
 def uwsgi_pypy_async_sleep(timeout):
+    """
+    uwsgi.async_sleep(timeout)
+    """
     if timeout > 0:
         wsgi_req = uwsgi_pypy_current_wsgi_req()
         lib.async_add_timeout(wsgi_req, timeout)
 uwsgi.async_sleep = uwsgi_pypy_async_sleep
 
-"""
-uwsgi.async_connect(addr)
-"""
+
 def uwsgi_pypy_async_connect(addr):
+    """
+    uwsgi.async_connect(addr)
+    """
     fd = lib.uwsgi_connect(ffi.new('char[]', addr), 0, 1)
     if fd < 0:
         raise Exception("unable to connect to %s" % addr)
@@ -778,37 +816,40 @@
 
 uwsgi.connection_fd = lambda: uwsgi_pypy_current_wsgi_req().fd
 
-"""
-uwsgi.wait_fd_read(fd, timeout=0)
-"""
+
 def uwsgi_pypy_wait_fd_read(fd, timeout=0):
+    """
+    uwsgi.wait_fd_read(fd, timeout=0)
+    """
     wsgi_req = uwsgi_pypy_current_wsgi_req()
     if lib.async_add_fd_read(wsgi_req, fd, timeout) < 0:
         raise Exception("unable to add fd %d to the event queue" % fd)
 uwsgi.wait_fd_read = uwsgi_pypy_wait_fd_read
 
-"""
-uwsgi.wait_fd_write(fd, timeout=0)
-"""
+
 def uwsgi_pypy_wait_fd_write(fd, timeout=0):
+    """
+    uwsgi.wait_fd_write(fd, timeout=0)
+    """
     wsgi_req = uwsgi_pypy_current_wsgi_req()
     if lib.async_add_fd_write(wsgi_req, fd, timeout) < 0:
         raise Exception("unable to add fd %d to the event queue" % fd)
 uwsgi.wait_fd_write = uwsgi_pypy_wait_fd_write
 
-"""
-uwsgi.ready_fd()
-"""
+
 def uwsgi_pypy_ready_fd():
+    """
+    uwsgi.ready_fd()
+    """
     wsgi_req = uwsgi_pypy_current_wsgi_req()
     return lib.uwsgi_ready_fd(wsgi_req)
 uwsgi.ready_fd = uwsgi_pypy_ready_fd
-    
 
-"""
-uwsgi.send(fd=None,data)
-"""
+
 def uwsgi_pypy_send(*args):
+    """
+    uwsgi.send(fd=None,data)
+    """
     if len(args) == 0:
         raise ValueError("uwsgi.send() takes at least 1 argument")
     elif len(args) == 1:
@@ -824,10 +865,11 @@
     return rlen
 uwsgi.send = uwsgi_pypy_send
 
-"""
-uwsgi.recv(fd=None,len)
-"""
+
 def uwsgi_pypy_recv(*args):
+    """
+    uwsgi.recv(fd=None,len)
+    """
     if len(args) == 0:
         raise ValueError("uwsgi.recv() takes at least 1 argument")
     elif len(args) == 1:
@@ -843,7 +885,7 @@
         raise IOError("unable to receive data")
     return ffi.string(data[0:rlen])
 uwsgi.recv = uwsgi_pypy_recv
-    
+
 """
 uwsgi.close(fd)
 """
@@ -854,10 +896,11 @@
 """
 uwsgi.disconnect = lambda: lib.uwsgi_disconnect(uwsgi_pypy_current_wsgi_req())
 
-"""
-uwsgi.websocket_recv()
-"""
+
 def uwsgi_pypy_websocket_recv():
+    """
+    uwsgi.websocket_recv()
+    """
     wsgi_req = uwsgi_pypy_current_wsgi_req()
     ub = lib.uwsgi_websocket_recv(wsgi_req)
     if ub == ffi.NULL:
@@ -867,10 +910,11 @@
     return ret
 uwsgi.websocket_recv = uwsgi_pypy_websocket_recv
 
-"""
-uwsgi.websocket_recv_nb()
-"""
+
 def uwsgi_pypy_websocket_recv_nb():
+    """
+    uwsgi.websocket_recv_nb()
+    """
     wsgi_req = uwsgi_pypy_current_wsgi_req()
     ub = lib.uwsgi_websocket_recv_nb(wsgi_req)
     if ub == ffi.NULL:
@@ -880,10 +924,11 @@
     return ret
 uwsgi.websocket_recv_nb = uwsgi_pypy_websocket_recv_nb
 
-"""
-uwsgi.websocket_handshake(key, origin)
-"""
+
 def uwsgi_pypy_websocket_handshake(key='', origin='', proto=''):
+    """
+    uwsgi.websocket_handshake(key, origin)
+    """
     wsgi_req = uwsgi_pypy_current_wsgi_req()
     c_key = ffi.new('char[]', key)
     c_origin = ffi.new('char[]', origin)
@@ -892,19 +937,21 @@
         raise IOError("unable to complete websocket handshake")
 uwsgi.websocket_handshake = uwsgi_pypy_websocket_handshake
 
-"""
-uwsgi.websocket_send(msg)
-"""
+
 def uwsgi_pypy_websocket_send(msg):
+    """
+    uwsgi.websocket_send(msg)
+    """
     wsgi_req = uwsgi_pypy_current_wsgi_req()
     if lib.uwsgi_websocket_send(wsgi_req, ffi.new('char[]', msg), len(msg)) < 0:
         raise IOError("unable to send websocket message")
 uwsgi.websocket_send = uwsgi_pypy_websocket_send
 
-"""
-uwsgi.chunked_read(timeout=0)
-"""
+
 def uwsgi_pypy_chunked_read(timeout=0):
+    """
+    uwsgi.chunked_read(timeout=0)
+    """
     wsgi_req = uwsgi_pypy_current_wsgi_req()
     rlen = ffi.new("size_t*")
     chunk = lib.uwsgi_chunked_read(wsgi_req, rlen, timeout, 0)
@@ -913,10 +960,11 @@
     return ffi.buffer(chunk, rlen[0])[:]
 uwsgi.chunked_read = uwsgi_pypy_chunked_read
 
-"""
-uwsgi.chunked_read_nb()
-"""
+
 def uwsgi_pypy_chunked_read_nb():
+    """
+    uwsgi.chunked_read_nb()
+    """
     wsgi_req = uwsgi_pypy_current_wsgi_req()
     rlen = ffi.new("size_t*")
     chunk = lib.uwsgi_chunked_read(wsgi_req, rlen, 0, 1)
@@ -924,17 +972,15 @@
         if lib.uwsgi_is_again() > 0:
             return None
         raise IOError("unable to receive chunked part")
+
     return ffi.buffer(chunk, rlen[0])[:]
 uwsgi.chunked_read_nb = uwsgi_pypy_chunked_read_nb
 
 
-def uwsgi_pypy_set_user_harakiri(x):
-    """
-    uwsgi.set_user_harakiri(sec)
-    """
-    wsgi_req = uwsgi_pypy_current_wsgi_req()
-    lib.set_user_harakiri(wsgi_req, x)
-uwsgi.set_user_harakiri = uwsgi_pypy_set_user_harakiri
+"""
+uwsgi.set_user_harakiri(sec)
+"""
+uwsgi.set_user_harakiri = lambda x: lib.set_user_harakiri(x)
 
 
 def uwsgi_pypy_get_logvar(key):
@@ -976,6 +1022,7 @@
 def uwsgi_pypy_continulet_wrapper(cont):
     lib.async_schedule_to_req_green()
 
+
 @ffi.callback("void()")
 def uwsgi_pypy_continulet_schedule():
     id = lib.uwsgi.wsgi_req.async_id
@@ -989,14 +1036,15 @@
 
     # this is called in the main stack
     if lib.uwsgi.p[modifier1].suspend:
-        lib.uwsgi.p[modifier1].suspend(ffi.NULL)    
+        lib.uwsgi.p[modifier1].suspend(ffi.NULL)
 
     # let's switch
     uwsgi_pypy_continulets[id].switch()
 
     # back to the main stack
     if lib.uwsgi.p[modifier1].resume:
-        lib.uwsgi.p[modifier1].resume(ffi.NULL) 
+        lib.uwsgi.p[modifier1].resume(ffi.NULL)
+
 
 @ffi.callback("void(struct wsgi_request *)")
 def uwsgi_pypy_continulet_switch(wsgi_req):
@@ -1005,17 +1053,18 @@
 
     # this is called in the current continulet
     if lib.uwsgi.p[modifier1].suspend:
-        lib.uwsgi.p[modifier1].suspend(wsgi_req)    
+        lib.uwsgi.p[modifier1].suspend(wsgi_req)
 
     uwsgi_pypy_continulets[id].switch()
 
     # back to the continulet
     if lib.uwsgi.p[modifier1].resume:
-        lib.uwsgi.p[modifier1].resume(wsgi_req) 
+        lib.uwsgi.p[modifier1].resume(wsgi_req)
 
     # update current running continulet
     lib.uwsgi.wsgi_req = wsgi_req
-    
+
+
 def uwsgi_pypy_setup_continulets():
     if lib.uwsgi["async"] < 1:
         raise Exception("pypy continulets require async mode !!!")
--- /dev/null
+++ b/t/php/test.php
@@ -0,0 +1,23 @@
+<?php
+
+# execute with:
+# uwsgi --ini t/php/config.ini &
+# curl http://localhost:8080/test.php
+
+set_error_handler(function() {
+	var_export(func_get_args());
+	echo "\nFAIL\n";
+	die;
+});
+
+session_start();
+$_SESSION['t'] = 't';
+session_commit();
+
+session_start();
+session_regenerate_id();
+session_commit();
+
+session_start();
+session_destroy();
+echo "PASS\n";
