Opened 9 years ago

Closed 7 years ago

Last modified 7 months ago

#3252 closed feature request (fixed)

having to call hs_add_root(__stginit_Foo) is a bit of a pain

Reported by: duncan Owned by: simonmar
Priority: high Milestone: 7.2.1
Component: Compiler (FFI) Version: 6.10.2
Keywords: Cc: michal.terepeta@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

For C code calling C functions exported from Haskell code, it has to jump through a couple hoops first. The call to hs_init() is fair enough and is specified by the FFI, however GHC also makes us call:

hs_add_root(__stginit_Foo);

for the top level Haskell module that exports the function we're interested in. If there are multiple such modules and they don't depend on each other then presumably we have to call them all.

Doing this is a bit annoying. It's not just that we have to call it, but we have to work out which symbols we need exactly. Are there any ways we could automate it? If the __stginit_* functions are really cheap then can we just have them called as constructor functions using gcc's __attribute__ ((constructor)) system. If they're slightly more expensive then perhaps they could be registered in a constructor and called by hs_init(). Or can we have them run lazily, eg have the exported C functions check that the module they're in has been initialised.

Change History (13)

comment:1 Changed 9 years ago by simonmar

difficulty: Unknown

Generating constructor functions in Haskell modules would be a bit tricky, because we'd have to generate code that has the C calling convention, and neither the NCG nor the mangler knows how to do that.

Something along the lines of the last method (have the exported C functions check that the module they're in has been initialised) might be possible. But we have to be careful not to add too much overhead to the call-in path.

I'll think some more about this.

comment:2 Changed 8 years ago by igloo

Milestone: 6.12.1

comment:3 Changed 8 years ago by igloo

Milestone: 6.12.16.14.1
Type of failure: None/Unknown

comment:4 Changed 8 years ago by lodi

I recently ran into this issue when building a shared library with a c-interface. A hand-built library (module CInterface, no package) would link fine. A cabal-built library (package test-0.0) would fail with:

./libHStest-0.0-ghc6.12.1.so: undefined reference to `__stginit_CInterface'

After some help from duncan:

> nm libHStest-0.0-ghc6.12.1.so | grep stginit
...
00004570 T __stginit_testzm0zi0_CInterface
00004500 T __stginit_testzm0zi0_CInterface_dyn
...

So it turns out that the package name and version are embedded into the symbol. This necessitates manually updating the c source files whenever the package version is incremented. The error is additionally confusing since the manual states that ghc will automatically export __stginit_Foo, and also since it isn't even reported until the consuming application is linked.

Some way to have ghc take care of this automatically would be much appreciated!

comment:5 Changed 8 years ago by simonmar

Yes, the package name and version are omitted when this is the main pacakge (the default). It is possible that different packages use the same module name, so it's not possible to use the __stginit_Foo form when the modules are being built as part of a package.

We'll put some thought into how to do the initialisation automatically.

comment:6 Changed 7 years ago by simonmar

Milestone: 7.0.17.2.1

comment:7 Changed 7 years ago by simonmar

Priority: normalhigh

comment:8 Changed 7 years ago by simonmar

See also #4417.

comment:9 Changed 7 years ago by michalt

Cc: michal.terepeta@… added

comment:10 Changed 7 years ago by simonmar

Owner: set to simonmar

I have work-in-progress to fix this.

comment:11 Changed 7 years ago by simonmar

Resolution: fixed
Status: newclosed

comment:12 Changed 6 years ago by simonmar

Milestone: 7.4.17.2.1

comment:13 Changed 7 months ago by Sergei Trofimovich <slyfox@…>

In a92ff5d6/ghc:

hs_add_root() RTS API removal

Before ghc-7.2 hs_add_root() had to be used to initialize haskell
modules when haskell was called from FFI.

commit a52ff7619e8b7d74a9d933d922eeea49f580bca8
("Change the way module initialisation is done (#3252, #4417)")
removed needs for hs_add_root() and made function a no-op.
For backward compatibility '__stginit_<module>' symbol was
not removed.

This change removes no-op hs_add_root() function and unused
'__stginit_<module>' symbol from each haskell module.

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>

Test Plan: ./validate

Reviewers: simonmar, austin, bgamari, erikd

Reviewed By: simonmar

Subscribers: rwbarton, thomie

Differential Revision: https://phabricator.haskell.org/D3460
Note: See TracTickets for help on using tickets.