douci1615 2017-06-22 12:41
浏览 123
已采纳

从Go调用NotifyIpInterfaceChange导致访问冲突异常

This is the first time I have had to make calls to native libraries from Go.

I am trying to setup event hooks with the windows libraries to listen for network interface changes, so far I have been successful with setting up a listener with NotifyAddrChange.

Now I am trying with NotifyIpInterfaceChange with the following code

package main

import (
    "golang.org/x/sys/windows"
    "log"
    "syscall"
    "unsafe"
)

var (
    modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")

    procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange")
)

type context struct{}

func main() {
    log.Printf("Loaded [iphlpapi.dll] at {%#v}", modiphlpapi.Handle())
    log.Printf("Found [NotifyIpInterfaceChange] at {%#v}", procNotifyIpInterfaceChange.Addr())

    context := &context{}
    interfaceChange := windows.Handle(0)

    ret, _, errNum := procNotifyIpInterfaceChange.Call(syscall.AF_UNSPEC, syscall.NewCallback(callback), uintptr(unsafe.Pointer(context)), 0, uintptr(interfaceChange))
    log.Printf("%#v %#v", ret, errNum)

}

func callback(callerContext, row, notificationType uintptr) uintptr {
    log.Printf("callback invoked by Windows API (%#v %#v %#v)", callerContext, row, notificationType)
    return 0
}

The code compiles fine and starts up without any issue, the problem happens once the function is invoke, then I get the following exception

D:\>event-listen_type2.exe
2017/06/22 22:12:39 Loaded [iphlpapi.dll] at {0x7ffac96f0000}
2017/06/22 22:12:39 Found [NotifyIpInterfaceChange] at {0x7ffac96f7e20}
Exception 0xc0000005 0x1 0x0 0x7ffac96f7edb
PC=0x7ffac96f7edb

syscall.Syscall6(0x7ffac96f7e20, 0x5, 0x0, 0x454170, 0x54d360, 0x0, 0x0, 0x0, 0xc042015350, 0xc042015300, ...)
        /usr/local/Cellar/go/1.8.3/libexec/src/runtime/syscall_windows.go:174 +0x6b
github.com/LiamHaworth/windows-network-events/vendor/golang.org/x/sys/windows.(*Proc).Call(0xc04203a620, 0xc042050300, 0x5, 0x5, 0x30, 0x4b12e0, 0x1, 0xc042050300)
        /Users/liam/git/go_path/src/github.com/LiamHaworth/windows-network-events/vendor/golang.org/x/sys/windows/dll_windows.go:139 +0x5c1
github.com/LiamHaworth/windows-network-events/vendor/golang.org/x/sys/windows.(*LazyProc).Call(0xc042050270, 0xc042050300, 0x5, 0x5, 0x1, 0xc04201a000, 0xc04202df78, 0x4043a3)
        /Users/liam/git/go_path/src/github.com/LiamHaworth/windows-network-events/vendor/golang.org/x/sys/windows/dll_windows.go:309 +0x66
main.main()
        /Users/liam/git/go_path/src/github.com/LiamHaworth/windows-network-events/main_windows.go:25 +0x229
rax     0x0
rbx     0xc3f10
rcx     0x1fb5cd87abfd0000
rdi     0x0
rsi     0x454170
rbp     0xc04202dc00
rsp     0x8fdf0
r8      0x8fb78
r9      0x7ffac96fb4c0
r10     0x0
r11     0x8fcf0
r12     0x0
r13     0xffffffee
r14     0x0
r15     0xaa
rip     0x7ffac96f7edb
rflags  0x10246
cs      0x33
fs      0x53
gs      0x2b

From some googling I know that exception type 0xc0000005 is a access violation thrown by the CPU when a program tries to access memory not allocated to it but looking through my code I can't tell where that is happening. All pointers passed are for items in the application.

Any help here would be magnificent.

  • 写回答

1条回答 默认 最新

  • douzong5057 2017-06-23 01:37
    关注

    According to documentation, the latest parameter of NotifyIpInterfaceChange is both in/out and need to be a pointer to HANDLE. Change the system call to:

    ret, _, errNum := procNotifyIpInterfaceChange.Call(syscall.AF_UNSPEC,
        syscall.NewCallback(callback),
        uintptr(unsafe.Pointer(context)), 
        0, 
        uintptr(unsafe.Pointer(&interfaceChange)))   //this must be pointer
    

    EDIT:
    As mentioned in the comment and this go-nuts discussion, for multi-threaded callback, import "C" need to be added, even if we don't use cgo.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?