GoLang(cgp) http.Client 获取请求从 Linux 守护进程挂起 [英] GoLang(cgp) http.Client get request hangs from Linux daemon process

查看:27
本文介绍了GoLang(cgp) http.Client 获取请求从 Linux 守护进程挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个简单的 GoLang 函数,它使用 http.Client 发出 HTTP GET 请求并打印响应字符串.然后我使用以下命令将其导出为 .so 文件中的 C 函数.

I have written a simple GoLang function which makes HTTP GET request using http.Client and prints the response string. I then exported it as C function in .so file using following command.

go build -o libapp.so -buildmode=c-shared libapp.go

然后使用这个 .SO 和 .h,从我的 C 测试程序中调用导出的 Go 函数.下面是我用来编译和构建我的 C 测试程序的命令.

Then using this .SO and .h, called exported Go function from my C test program. Below is the command I used to compile and build my C test program.

gcc -o goclient goclient.c ./libapp.so

这里是 GoLang 中的 CheckConnection 函数

Here is CheckConnection function in GoLang

var file io.Writer

//export CheckConnection
func CheckConnection() {

path := "/opt/logs/gologs.txt"
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
    log.Fatal(err)    
}
file = f
log.SetOutput(file)
log.Print("---------Logging started---------")
log.Print("Hello from CheckConnection\r\n")

log.Print("CheckConnection creating http.Client: step1")

var netTransport = &http.Transport{
  Dial: (&net.Dialer{
Timeout: 10 * time.Second,
  }).Dial,
  TLSHandshakeTimeout: 10 * time.Second,    
}
log.Print("CheckConnection creating http.Client: step2")

var myClient = &http.Client{
  Timeout: time.Second * 10,
  Transport: netTransport,
}
log.Print("CheckConnection creating http.Client: step3")

res,err := myClient.Get("https://www.google.com")
log.Print("CheckConnection creating http.Client: step4")
if err!= nil {
log.Print("Error ",err)
}
log.Print("CheckConnection creating http.Client: step5")
data,_ := ioutil.ReadAll(res.Body)
log.Print("CheckConnection creating http.Client: step6")
res.Body.Close()
log.Print("CheckConnection creating http.Client: step7")
log.Print("Resp code ",res.StatusCode)
log.Print("Data ",data)

defer log.Print("Returning from CheckConnection");

}

线程在下面一行被阻塞,不会超时或出错 -

Thread gets blocked at below line, does not timeout or gives error -

 res,err := myClient.Get("https://www.google.com")

当 CheckConnection() 函数被 Daemon 进程调用时会发生这种情况.如果我从 C,C++ main() 进程调用这个函数,那么它就可以工作了.我在 GitHub https://github.com/golang/go/issues/47077 上报告了同样的问题.它具有重现问题的示例代码 (Sample.zip).

This happens when CheckConnection() function gets called from Daemon process. If I call this function from C,C++ main() process then it works. I have reported same issue on GitHub https://github.com/golang/go/issues/47077. It has sample code to reproduce the issue (Sample.zip).

请参考 GitHub issue https://github.com/golang/go/issues/47077 用于示例可重现代码.

Please refer to GitHub issue https://github.com/golang/go/issues/47077 for sample reproducible code.

在下面添加 go env

Adding go env below

GO111MODULE=""
GOARCH="386"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="386"
GOHOSTOS="linux"
GOINSECURE="golang.org,googlesource.com"
GOMODCACHE="/home/nilesh/golang/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/nilesh/golang"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_386"
GOVCS=""
GOVERSION="go1.16.4"
GCCGO="gccgo"
GO386="sse2"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/nilesh/SVN/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m32 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build718813889=/tmp/go-build -gno-record-gcc-switches"

推荐答案

在 linux 上的 C/C++ 程序中使用 cgp 共享库时,如果您从分叉进程调用这些函数,请确保您应该考虑以下几点.

When using cgp shared library in your C/C++ program on linux and if you are calling these functions from forked process then make sure you should consider below points.

  1. 不要静态链接共享库,而是使用 dlopen、dlsym、dlclose 动态加载它.

  1. Do not statically link the shared library, instead load it dynamically using dlopen, dlsym, dlclose.

确保在执行上述操作时您没有在链接期间提供共享库名称

Make sure while doing above you are not providing shared lib name during linking

这解决了我的问题,我能够从我的分叉进程进行网络调用.

This solved my problem and I am able to to make network calls from my forked process.

这篇关于GoLang(cgp) http.Client 获取请求从 Linux 守护进程挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆