Issue #155 invalid

Segfault in cffi.string (Windows)

Marc Schlaich
created an issue

Exception (captured with faulthandler):

Fatal Python error: Segmentation fault

Current thread 0x00000a78:
  File "cffi\api.py", line 253 in string
  File "pydde\client.py", line 102 in _get_data

Code:

data = ffi.string(ffi.cast('LPCSTR', data))

Platform:

  • Windows XP
  • Python 2.7

Comments (9)

  1. Marc Schlaich reporter

    A strange pointer:

    data <cdata 'unsigned char *' 0x00000004>
    

    I guess this is an error from my side (or the platform). However, this should not crash with a segfault...

  2. Marc Schlaich reporter

    I looks like the cause of the issue is some synchronization issue with a callback. Basically I have various library calls which should occur atomically, e.g.

    lib.func1()
    lib.func2()
    

    But with a callback set up it can happen that CFFI calls the callback between the two calls which means the data is corrupt for the second function call. How are these callbacks realized? Some stack switching like greenlet? Is there any way to prevent the callback from occur while calling C functions?

  3. Armin Rigo

    Why shouldn't it crash with a segfault? That's like writing C code like printf("%s", data);. If data equals (unsigned char *)0x0004 you get a segfault.

    About callbacks: I'm not sure what you mean by "callback". In the context of CFFI, a callback is a C function pointer that, when called from some C code, invokes a Python function. There is no stack-switching and no non-determinism involved here. Unless you mean some destructor function set up by ffi.gc()?

  4. Marc Schlaich reporter

    Why shouldn't it crash with a segfault?

    Well, usually you would expect that Python code never crashes. It might be asked too much in this context, though...

    In the context of CFFI, a callback ...

    Yes, and this callback can be invoked from the C library every time you call out to C and the GIL is released. At least this is the behavior I experience on my setup. It is an event callback so it is per se non-deterministic.

    AFAIS every call to C code is a possible entry point for a callback from C so it looks like some sort of implicit stack switching. Would synchronization primitives (threading.Lock, ...) help in my case?

  5. Armin Rigo

    You're not taking the correct point of view :-) The approach of CFFI is to give unadorned raw access to C code, including all the things you can do that are "unsafe" and can lead to segfaults. Basically it's like writing the program in C for those parts that manipulate CFFI data and functions directly. I can't answer the question of how to protect against callbacks invoked at the wrong point in time; the details depend completely on what the C library specifies and how you're supposed to use it when you're writing C code. There is no single answer to that.

  6. Marc Schlaich reporter

    The approach of CFFI is to give unadorned raw access to C code, including all the things you can do that are "unsafe" and can lead to segfaults.

    Ok. in this case I'm closing this issue.

    About callbacks: I assume that CFFI and I am doing the right thing here and the issue is on the remote side. But it looks like that I'm able to workaround this issue.

  7. Log in to comment