Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go: dlopen returns before init has finished #12639

Closed
chamaken opened this issue Sep 16, 2015 · 1 comment
Closed

cmd/go: dlopen returns before init has finished #12639

chamaken opened this issue Sep 16, 2015 · 1 comment

Comments

@chamaken
Copy link

version and OS

$ go version  
go version go1.5.1 linux/amd64

What did you do?
I tried to dlopen c-shared go object. Please check sample code below:
main.c

/* cc -export-dynamic main.c -ldl */
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static volatile int n;

int add(void)
{
        return ++n;
}

int main(int argc, char *argv[])
{
        void *handle;

        if ((handle = dlopen(argv[1], RTLD_NOW)) == NULL) {
                fprintf(stderr, "dlopen: %s - %s\n", argv[1], dlerror());
                exit(EXIT_FAILURE);
        }
        /* sleep(1); */
        printf("n: %d\n", n);

        return EXIT_SUCCESS;
}

dso.go

// go build -buildmode=c-shared dso.go
package main

/*
extern int add(void);
#cgo LDFLAGS: -Wl,--unresolved-symbols=ignore-all
*/
import "C"
import "fmt"

func init() {
        fmt.Printf("init finished: %d\n", C.add())
}

func main() {}

comple both as commented top of the code, and try ./a.out ./dso

What did you expect to see?
I expected to see a message and "n: 1". in dlopen(3)

Constructor  routines  are  executed  before dlopen() returns,  
and destructor routines are executed before dlclose() returns.

but (my, users) constructor, func init() seems to be defered.

What did you see instead?
It shows "n: 0", I can see the expected by enabling sleep(1), in comment.

@minux
Copy link
Member

minux commented Sep 16, 2015

Your C program has to call at least one Go callback (exported function)
to make sure that the Go runtime will finish initializing before your
program exits. (that's the reason why adding sleep(1) will allow the
message to show)

Go's runtime initialization is async, that is, when dlopen returns, it's not
done yet. It's just started in another thread. You need to call a cgo export
to synchronize with it.

@minux minux closed this as completed Sep 16, 2015
@golang golang locked and limited conversation to collaborators Sep 22, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants