Embedding D Shared Library in WSGI Web Server

John McFarlane via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Nov 3 11:41:19 PST 2014


On Tuesday, 28 October 2014 at 09:34:33 UTC, Chris wrote:
> On Tuesday, 28 October 2014 at 00:16:03 UTC, John McFarlane 
> wrote:
>> Hi,
>>
>> I've written a modest shared library in D that I'd like to 
>> call directly from a Python web server (Linux/OS X, Apache, 
>> WSGI, Pyramid). I can call it reliably from within Python unit 
>> tests but on a running server, the library causes a SIGSEGV as 
>> soon as I try anything as complicated as a writeln call. Under 
>> Linux, I've tried using Pyd, CFFI and ctypes to bind the 
>> native .so to Python with the same result. I've tried calling 
>> Runtime.initialize();from an init function on server startup 
>> and from the D function being called as part of the web 
>> request. I've even tried writing a shim in C to make these 
>> calls and call through to the D.
>>
>> I've compiled with DMD and GDC with a variety of switches. 
>> Currently my build command looks like:
>>
>>    dmd ./d/*.d -version=library -release -shared -O -inline 
>> -defaultlib=libphobos2.so -fPIC -oflibgusteau.so
>>
>> The extern(C) function takes a string and returns a string. 
>> I've tried holding onto a pointer to the returned string and 
>> passing in an adequately sized byte array from Python. Smaller 
>> strings seem to cause a crash with lower probability but 
>> typically the input and output strings are a few KB in size 
>> and consistently crash. I taken measures to ensure that they 
>> are correctly encoded and null terminated. I've also tried 
>> disabling the GC, calling terminate on function exit (after 
>> copying result into received buffer) and various other 
>> measures in an attempt to get something working.
>>
>> I'm guessing that the web server spawns/relies on a thread or 
>> process for each request and I've read that runtime 
>> initialization should be invoked from the main thread. Does 
>> this always mean the first thread that was created on process 
>> start up or does it just have to be consistent? If calling 
>> from a thread other than the one used to initialize, is that a 
>> problem? Are other threads created when GC is invoked which 
>> might last past the extern function being called and if so, 
>> can I prevent this by controlling collection explicitly?
>>
>> Thanks, John
>
> I had a similar problem with a DLL for Python. The reason my 
> DLL would crash were some writeln statements. After removing 
> them it worked fine. I suppose the writeln messes things up, be 
> it because of threads or because of conflicts in the file 
> system (remember writeln is a file system operation). I suggest 
> you have your lib not print things to console, but use a 
> different mechanism instead, e.g. pass a string back to Python 
> and have Python do the printing (if needs be).
>
> You could also try to set your lib up as a small socket server 
> that waits for input and answers. That usually works for me.

Thanks for the suggestion. I looked into removing all of my 
writeln calls and
found the I still had the same problem. Simply a call to 
to!string with the
input char* is enough to cause a crash. I will go with the socket 
server as a
last resort but it would be much easier (especially from a 
testing POV) if I
could call the native D code directly from the web server.


More information about the Digitalmars-d-learn mailing list