STINNER Victor added the comment:

>> Did you see some errors or warnings when running your application with 
>> asyncio in debug mode?

> No, but I'll try. I doubt the problem is in asyncio itself because it's 
> mostly written in Python. This looks like a garbage collection issue.

Sorry, you're wrong: the proactor event loop heavily uses the _overlapped 
module which is implemented in C. A crash in the garbage collector is more 
likely a bug in asyncio/your application, than a bug in Python itself.

Please enable asyncio debug mode, ResourceWarning, enable DEBUG log level, and 
check if you get some errors. For example, "GetQueuedCompletionStatus() 
returned an unexpected event" usually means that you will quickly get a memory 
corruption...

If possible, write all asyncio logs at DEBUG log level and attach them to the 
issue. Using the logging module, it's possible to add a custom handler for 
"asyncio". Example:
---
import asyncio
import logging

logging.basicConfig()

logger = asyncio.log.logger
output = open("asyncio.log", "a")
handler = logging.StreamHandler(output)
handler.setLevel(logging.DEBUG)
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)

asyncio.log.logger.debug("plop")
output.close()
---

> python34_d.dll!PyList_New(__int64 size=0)  Line 159 + 0xc bytes

So the crash occurred again during a call to PyList_New(0) which triggerred a 
garbage collection. The backtrace looks more reliable: _PyObject_GC_Malloc(56).

> msvcr100d.dll!_wassert(const wchar_t * expr=0x0000000063220618, const wchar_t 
> * filename=0x00000000632205e0, unsigned int lineno=364)  Line 153
> python34_d.dll!update_refs(_gc_head * containers=0x000000006338cfc0)  Line 
> 364 + 0x2b bytes

This assertion contains a long comment which explains when the assertion can 
fail.

        /* Python's cyclic gc should never see an incoming refcount
         * of 0:  if something decref'ed to 0, it should have been
         * deallocated immediately at that time.
         * Possible cause (if the assert triggers):  a tp_dealloc
         * routine left a gc-aware object tracked during its teardown
         * phase, and did something-- or allowed something to happen --
         * that called back into Python.  gc can trigger then, and may
         * see the still-tracked dying object.  Before this assert
         * was added, such mistakes went on to allow gc to try to
         * delete the object again.  In a debug build, that caused
         * a mysterious segfault, when _Py_ForgetReference tried
         * to remove the object from the doubly-linked list of all
         * objects a second time.  In a release build, an actual
         * double deallocation occurred, which leads to corruption
         * of the allocator's internal bookkeeping pointers.  That's
         * so serious that maybe this should be a release-build
         * check instead of an assert?
         */
        assert(_PyGCHead_REFS(gc) != 0);

To come back to asyncio and the proactor event loop: the implementations of the 
proactor event loop is still young and probably unstable. Would it be possible 
to test again with fewer clients (500 clients or less to not hit the select() 
limit on Windows) with selector event loop?

A crash in the garbage collector can be caused by a memory corruption. I fixed 
a lot of memory corruption caused by internal objects uesd in the proactor 
event loop.

Can you check if asyncio.windows_events._BaseWaitHandleFuture is used? This 
class is used by IocpProactor.wait_for_handle() which is called by 
_WindowsSubprocessTransport. But you wrote you the server (where the crash 
occurs) doesn't run subprocesses.

I never tried the proactor event loop with threads. Are you using asyncio code 
outside the main thread? asyncio is not thread-safe at all :-p Are you using a 
single event loop or one event loop per thread?

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue23187>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to