Skip to content

runtime: windows.LoadLibrary no longer triggers init functions of Go DLLs #75949

@mjwhitta

Description

@mjwhitta

Go version

go version go1.25.0 linux/amd64

Output of go env in your module/workspace:

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/user/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/user/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1578872999=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/home/user/code/go/godll/go.mod'
GOMODCACHE='/home/user/.go/v1.25.0/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/user/.go/v1.25.0'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/user/.cache/gvm/use'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/user/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/user/.cache/gvm/use/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.25.0'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

I have two pieces of source code below. I've attached screenshots of the main.go code running with go version v1.24.9 and go version 1.25.0. With v1.24.9 I correctly see "hello Go" three times: once as an exe, once with rundll32, and once with LoadLibrary via loader.exe. After switching to v1.25.0 (and anything newer), I only see the "hello Go" the first two times: once as an exe and once with rundll32. The LoadLibrary call in loader.exe does not seem to trigger the init() call anymore. I have tested the loader.exe with C DLLs and they work as expected via DllMain. This seems to be specific to only Go DLLs compiled with v1.25.0 and newer. I've also tested with my own DllMain with no success. It looks like any calls to Go from C, when called from LoadLibrary, never execute. I didn't see anything in the v1.25.0 release notes that might account for this change.

loader.go

//go:build windows

package main

import (
	"fmt"

	"golang.org/x/sys/windows"
)

func main() {
	if _, e := windows.LoadLibrary("./goplay.dll"); e != nil {
		println(e.Error())
	}

	fmt.Println("Press enter to exit")
	fmt.Scanln()
}

Compiled with:

$ GOOS=windows go build --buildvcs=false --ldflags="-s -w" -o loader.exe --trimpath ./loader.go

main.go

//go:build windows

package main

import (
	"C"

	"github.com/mjwhitta/win/dbg"
)

func init() {
	dbg.Printf("hello Go")
}

func main() {}

//export Start
func Start() {}

Compiled as exe with:

$ CC="x86_64-w64-mingw32-gcc" \
CGO_ENABLED="1" \
CXX="x86_64-w64-mingw32-g++" \
GOARCH="amd64" \
GOOS="windows" \
go build --buildvcs=false --ldflags="-s -w" -o goplay.exe --trimpath main.go

Compiled as dll with:

$ CC="x86_64-w64-mingw32-gcc" \
CGO_ENABLED="1" \
CXX="x86_64-w64-mingw32-g++" \
GOARCH="amd64" \
GOOS="windows" \
go build --buildmode="c-shared" --buildvcs=false --ldflags="-s -w" -o goplay.dll --trimpath main.go

What did you see happen?

v1.24.9

Image

v1.25.0

Image

What did you expect to see?

I expected to see `hello Go" three times in both cases.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.OS-Windowscompiler/runtimeIssues related to the Go compiler and/or runtime.help wanted

    Type

    No type

    Projects

    Status

    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions