problem with FFI and libsane

Simon Marlow marlowsd at gmail.com
Thu Jun 7 13:08:44 CEST 2012


On 06/06/2012 06:59, Ganesh Sittampalam wrote:

> I'm having some trouble making Haskell bindings to libsane (a scanner
> access library: http://www.sane-project.org/)
>
> When I build the cut down sample of my code (below) with GHC 7.4.1 with
> the non-threaded runtime, it hangs at runtime in the call to
> c'sane_get_devices (after printing "go"). Pressing ^C causes it to
> continue and print "done" before exiting.
>
> If I compile with GHC 7.2.2 non-threaded, it doesn't hang, printing
> first "go" then "done" after a few seconds. That pause is expected, as
> it's also seen in the equivalent C version (also below).
>
> If I switch to the threaded runtime, then things go wrong differently.
> Most of the time there's a hang after "go" and after pressing ^C they
> just exit immediately, without printing "done". This doesn't change
> between 7.2.2 and 7.4.1. Occasionally, things do work and I get "go"
> then "done".
>
> All these symptoms seem to point to some kind of threading problem, and
> I believe that libsane is using pthreads, although ldd doesn't report it
> and strace only shows it loading the library.
>
> The platform is Linux x86, and I've reproduced the behaviour on two
> different machines (Debian and Ubuntu). I've also tried with GHC
> 7.4.1.20120508, the most recent i386 snapshot I could fine.
>
> Is there anything obvious I'm doing wrong, or something I could try next?

I don't completely understand what is going wrong here, but it looks 
like an interaction between the RTS's use of a timer signal and the 
libsane library.  You can make it work by turning off GHC's timer with 
+RTS -V0.

There were some changes in this area in 7.4.1, in particular that the 
non-threaded RTS now uses a realtime interval timer, whereas in previous 
versions it used a CPU time interval timer.  The threaded RTS has always 
used a realtime timer.

The signal has always been SIGVTALRM, as far as I can tell.  Which is 
confusing - if the signal had changed, I could understand that being the 
cause of the difference in behaviour.  Perhaps it is just that system 
calls are being interrupted by the signal more often than they were 
before, and libsane does not properly handle EINTR.  I looked at the 
strace output and can't see any use of a signal by libsane.

Cheers,
	Simon


>
> Cheers,
>
> Ganesh
>
> Haskell code:
>
> {-# LANGUAGE ForeignFunctionInterface #-}
> import Foreign.Marshal.Alloc
> import Foreign.Ptr
> import System.IO
> import Foreign.C.Types
>
> foreign import ccall "sane_init" c'sane_init
>    :: Ptr CInt ->  Callback ->  IO CUInt
>
> type Callback = FunPtr (Ptr CChar ->  Ptr CChar ->  Ptr CChar ->  IO ())
>
> foreign import ccall "sane_exit" c'sane_exit
>    :: IO ()
>
> -- the () in the ptr type is incorrect, but in
> -- this cut-down example we never try to dereference it
> foreign import ccall "sane_get_devices" c'sane_get_devices
>    :: Ptr (Ptr (Ptr ())) ->  CInt ->  IO CUInt
>
>
> main :: IO ()
> main = do
>     hSetBuffering stdout NoBuffering
>     _<- c'sane_init nullPtr nullFunPtr
>     putStrLn "go"
>     ptr<- malloc
>     _<- c'sane_get_devices ptr 0
>     putStrLn "done"
>     c'sane_exit
>
>
> C code:
>
> #include<sane/sane.h>
> #include<stdlib.h>
>
> int main()
> {
>     sane_init(NULL, NULL);
>     puts("go");
>     const SANE_Device **ptr;
>     sane_get_devices(&ptr, 0);
>     puts("done");
>     sane_exit();
> }
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users at haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users




More information about the Glasgow-haskell-users mailing list