So I'm trying to integrate libuv into Pixie, and all was going well, but I'm hitting a bit of a snag when it comes to opening files. I've tried several things, but my latest iteration is this: https://github.com/pixie-lang/pixie/blob/async-io-file/pixie/vm/libs/uv_file... When running this in CPython it crashes on the call to uv_fs_read with the CPython error "Fatal Python error: GC object already tracked". From what I can tell, this means something has overwritten Python's memory somehow. The odd thing is, I'm sure I have the signature of the file correct: UV_EXTERN int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf, size_t length, int64_t offset, uv_fs_cb cb); And this doesn't seem to be a problem from libuv, because this is my stacktrace from the crash: Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_kernel.dylib 0x00007fff8e83c866 __pthread_kill + 10 1 libsystem_pthread.dylib 0x00007fff88f2835c pthread_kill + 92 2 libsystem_c.dylib 0x00007fff9019cb1a abort + 125 3 org.python.python 0x0000000100c73ec1 Py_FatalError + 49 4 org.python.python 0x0000000100bfc523 PyFrame_New + 598 5 org.python.python 0x0000000100c55a74 PyEval_EvalCodeEx + 74 6 org.python.python 0x0000000100bfd796 0x100bd6000 + 161686 7 org.python.python 0x0000000100bdff72 PyObject_Call + 101 8 org.python.python 0x0000000100bea9a7 0x100bd6000 + 84391 9 org.python.python 0x0000000100bdff72 PyObject_Call + 101 10 org.python.python 0x0000000100c281b4 0x100bd6000 + 336308 11 org.python.python 0x0000000100c25091 0x100bd6000 + 323729 12 org.python.python 0x0000000100c0f308 PyObject_RichCompare + 129 13 org.python.python 0x0000000100c5694e PyEval_EvalFrameEx + 1937 14 org.python.python 0x0000000100c5c864 0x100bd6000 + 551012 15 org.python.python 0x0000000100c594d4 PyEval_EvalFrameEx + 13079 16 org.python.python 0x0000000100c56093 PyEval_EvalCodeEx + 1641 17 org.python.python 0x0000000100bfd796 0x100bd6000 + 161686 Anyone have any ideas? Thanks, Timothy
you should really use "with" sentence with scoped buffers, otherwise you're leaking memory. Same goes for lltype.malloc(flavor='raw'), you need to lltype.free it. I don't think that causes crashes though, I would need to take a deeper look into the incantation too. How do I get a crash? Is there a failing test? On Mon, Nov 10, 2014 at 6:36 AM, Timothy Baldridge <tbaldridge@gmail.com> wrote:
So I'm trying to integrate libuv into Pixie, and all was going well, but I'm hitting a bit of a snag when it comes to opening files. I've tried several things, but my latest iteration is this:
https://github.com/pixie-lang/pixie/blob/async-io-file/pixie/vm/libs/uv_file...
When running this in CPython it crashes on the call to uv_fs_read with the CPython error "Fatal Python error: GC object already tracked". From what I can tell, this means something has overwritten Python's memory somehow. The odd thing is, I'm sure I have the signature of the file correct:
UV_EXTERN int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf, size_t length, int64_t offset, uv_fs_cb cb);
And this doesn't seem to be a problem from libuv, because this is my stacktrace from the crash:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_kernel.dylib 0x00007fff8e83c866 __pthread_kill + 10 1 libsystem_pthread.dylib 0x00007fff88f2835c pthread_kill + 92 2 libsystem_c.dylib 0x00007fff9019cb1a abort + 125 3 org.python.python 0x0000000100c73ec1 Py_FatalError + 49 4 org.python.python 0x0000000100bfc523 PyFrame_New + 598 5 org.python.python 0x0000000100c55a74 PyEval_EvalCodeEx + 74 6 org.python.python 0x0000000100bfd796 0x100bd6000 + 161686 7 org.python.python 0x0000000100bdff72 PyObject_Call + 101 8 org.python.python 0x0000000100bea9a7 0x100bd6000 + 84391 9 org.python.python 0x0000000100bdff72 PyObject_Call + 101 10 org.python.python 0x0000000100c281b4 0x100bd6000 + 336308 11 org.python.python 0x0000000100c25091 0x100bd6000 + 323729 12 org.python.python 0x0000000100c0f308 PyObject_RichCompare + 129 13 org.python.python 0x0000000100c5694e PyEval_EvalFrameEx + 1937 14 org.python.python 0x0000000100c5c864 0x100bd6000 + 551012 15 org.python.python 0x0000000100c594d4 PyEval_EvalFrameEx + 13079 16 org.python.python 0x0000000100c56093 PyEval_EvalCodeEx + 1641 17 org.python.python 0x0000000100bfd796 0x100bd6000 + 161686
Anyone have any ideas?
Thanks,
Timothy
_______________________________________________ pypy-dev mailing list pypy-dev@python.org https://mail.python.org/mailman/listinfo/pypy-dev
Hi Timothy,
From the docs, the signature of uv_fs_read() is this (http://docs.libuv.org/en/latest/fs.html#c.uv_fs_read):
int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb) This seems to differ from what you're reporting. The "bufs" and "nbufs" are not a pointer and size of a resulting buffer, but instead they are an array of buffers (possibly more than one), and the length of this array (i.e. the number of buffers). Each buffer is described by a uv_buf_t. This is more like preadv(2) than read(2). A bientôt, Armin.
So I think I've narrowed it down a bit to this: it seems to only happen when I can one of these libuv functions for the second time. The second test in this file throws the exception: https://github.com/pixie-lang/pixie/blob/async-io-file/pixie/vm/libs/test/te... " https://github.com/pixie-lang/pixie/blob/async-io-file/pixie/vm/libs/test/te... " All I'm doing here is opening a file (and never closing it, but that shouldn't be a problem). The code in FSOpen is even cleaning up the buffers I allocate this time. A bit of background on the process, FSOpen is a UVFunction. The function execute_uv_func, creates a continuation from the current stacklet and then calls .execute_uv passing it the uv loop and the continuation (k). Once libuv calls the callback fs_cb, the continuation is put into a list of pending stacklets and the loop inside with_stacklets will continue its execution at some time in the future. The only libuv functions called by this code is uv_fs_open, uv_fs_cleanup, and uv_run. The first test runs fine, but the second causes the crash. Timothy On Mon, Nov 10, 2014 at 12:38 AM, Armin Rigo <arigo@tunes.org> wrote:
Hi Timothy,
From the docs, the signature of uv_fs_read() is this (http://docs.libuv.org/en/latest/fs.html#c.uv_fs_read):
int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
This seems to differ from what you're reporting. The "bufs" and "nbufs" are not a pointer and size of a resulting buffer, but instead they are an array of buffers (possibly more than one), and the length of this array (i.e. the number of buffers). Each buffer is described by a uv_buf_t. This is more like preadv(2) than read(2).
A bientôt,
Armin.
-- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth)
Hi Timothy, We're talking past each other. I think that I already found that your code is not correct according to the docs. You need to fix the signature of uv_fs_read() and create an array 'uv_buf_t[]', possibly of length 1. I may be wrong though. A bientôt, Armin.
That could be true for uv_fs_read, but in the minimal test case (in my last email) I'm only opening a file 10 times, after the first few iterations of opening the file (2-3 times) that test crashes. Timothy On Mon, Nov 10, 2014 at 7:52 AM, Armin Rigo <arigo@tunes.org> wrote:
Hi Timothy,
We're talking past each other. I think that I already found that your code is not correct according to the docs. You need to fix the signature of uv_fs_read() and create an array 'uv_buf_t[]', possibly of length 1. I may be wrong though.
A bientôt,
Armin.
-- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth)
So I hacked on this more over my lunch break and am still completely stumped, I've removed all deallocation in order to make sure I'm not double-freeing something (make it stop crashing then make it stop leaking is the idea). No dice. The only thing I can figure out is that perhaps rffi is somehow freeing something I don't want it to free? Looking at the internals of rffi.llexternal, I see that it sometimes auto frees stuff, but the only things I'm passing in are raw buffers, voidp, integers, or the callback. Since this is libuv, the library may hold onto stuff like the filename even after the call to uv_fs_open completes. The idea being it will call the callback when the operation completes, but only during a call to uv_run. So all this looks correct to me, but I get the feeling that rffi must be doing some magic somewhere that I don't want. Any input would be awesome, I've been hacking on this for about half a week now and I'm completely stumped. Timothy On Mon, Nov 10, 2014 at 7:55 AM, Timothy Baldridge <tbaldridge@gmail.com> wrote:
That could be true for uv_fs_read, but in the minimal test case (in my last email) I'm only opening a file 10 times, after the first few iterations of opening the file (2-3 times) that test crashes.
Timothy
On Mon, Nov 10, 2014 at 7:52 AM, Armin Rigo <arigo@tunes.org> wrote:
Hi Timothy,
We're talking past each other. I think that I already found that your code is not correct according to the docs. You need to fix the signature of uv_fs_read() and create an array 'uv_buf_t[]', possibly of length 1. I may be wrong though.
A bientôt,
Armin.
-- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth)
-- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth)
The plot thickens even more. I tried several other things, and was surprised to find that a call to uv_timeout works just fine, that call takes a callback, but no strings and never stores the strings internally. On a whim I translated the entire thing (without a JIT) and everything I throw at it runs without a problem. Could this just be an issue with ffi and CPython? Timothy On Mon, Nov 10, 2014 at 1:16 PM, Timothy Baldridge <tbaldridge@gmail.com> wrote:
So I hacked on this more over my lunch break and am still completely stumped, I've removed all deallocation in order to make sure I'm not double-freeing something (make it stop crashing then make it stop leaking is the idea). No dice.
The only thing I can figure out is that perhaps rffi is somehow freeing something I don't want it to free? Looking at the internals of rffi.llexternal, I see that it sometimes auto frees stuff, but the only things I'm passing in are raw buffers, voidp, integers, or the callback.
Since this is libuv, the library may hold onto stuff like the filename even after the call to uv_fs_open completes. The idea being it will call the callback when the operation completes, but only during a call to uv_run. So all this looks correct to me, but I get the feeling that rffi must be doing some magic somewhere that I don't want.
Any input would be awesome, I've been hacking on this for about half a week now and I'm completely stumped.
Timothy
On Mon, Nov 10, 2014 at 7:55 AM, Timothy Baldridge <tbaldridge@gmail.com> wrote:
That could be true for uv_fs_read, but in the minimal test case (in my last email) I'm only opening a file 10 times, after the first few iterations of opening the file (2-3 times) that test crashes.
Timothy
On Mon, Nov 10, 2014 at 7:52 AM, Armin Rigo <arigo@tunes.org> wrote:
Hi Timothy,
We're talking past each other. I think that I already found that your code is not correct according to the docs. You need to fix the signature of uv_fs_read() and create an array 'uv_buf_t[]', possibly of length 1. I may be wrong though.
A bientôt,
Armin.
-- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth)
-- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth)
-- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth)
Hi Timothy, I did a git checkout of the branch async-io-file; then "cd pixie/pixie/vm/libs/test"; then "touch README.md" (unsure how you're supposed to run from the top directory); then: PYTHONPATH=~/git/pixie:~/pypysrc python -m unittest test_uv_file It seems to work for me (Ran 2 tests in xx s; OK). Is that how you're supposed to get the crash? A bientôt, Armin.
participants (3)
-
Armin Rigo
-
Maciej Fijalkowski
-
Timothy Baldridge