[BUG] Should handle EINTR
eubnara opened this issue · 5 comments
It keeps disconnected when using go1.14.11 or go1.15.4.
I think since golang/go#38033, golang handles EINTR.
To Reproduce
Steps to reproduce the behavior:
- Using Golang >= 1.15
- It keeps disconnected.
Expected behavior
Keep connected
Versions (please complete the following information, if relevant):
- Software version: 1.8.0
- OS: Ubuntu
- Golang version: 1.15.4
Additional context
Add any other context about the problem here.
I'm suffering a problem.
(And also I failed to run latest version with go get
command so I just run go run
on source code =>
gotty-client (master) $ pwd
/home/eub/go/src/github.com/moul/gotty-client/cmd/gotty-client
gotty-client (master) $ go run main.go -D http://****
)
I tried to print out the error in the writeLoop
.
And I found interrupted system call
message.
$ go run main.go -D http://****
DEBU[0000] Fetching auth token auth-token: "http://****/auth_token.js"
DEBU[0000] Auth-token: "****"
DEBU[0000] Connecting to websocket: "ws://****/ws"
DEBU[0000] Sending arguments and auth-token
DEBU[0000] Sending ping
DEBU[0000] Unhandled protocol message: json pref: {}
$ interrupted system call
DEBU[0000] writeLoop suicide
DEBU[0000] termsizeLoop died
DEBU[0000] readLoop died
DEBU[0000] Client.Loop() exiting
I just ignore EINTR
and the connection is not disconnected.
gotty-client.go
import (
"crypto/tls"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
"regexp"
+ "syscall"
"strings"
"sync"
"time"
"github.com/containerd/console"
"github.com/creack/goselect"
"github.com/gorilla/websocket"
"github.com/sirupsen/logrus"
)
...
...
func (c *Client) writeLoop(wg *sync.WaitGroup) poisonReason {
defer wg.Done()
fname := "writeLoop"
buff := make([]byte, 128)
rdfs := &goselect.FDSet{}
reader := io.ReadCloser(os.Stdin)
pr := NewEscapeProxy(reader, c.EscapeKeys)
defer reader.Close()
for {
select {
case <-c.poison:
/* Somebody poisoned the well; die */
return die(fname, c.poison)
default:
}
rdfs.Zero()
rdfs.Set(reader.(exposeFd).Fd())
err := goselect.Select(1, rdfs, nil, nil, 50*time.Millisecond)
if err != nil {
- return openPoison(fname, c.poison)
+ fmt.Println(err)
+ if err != syscall.EINTR {
+ return openPoison(fname, c.poison)
+ }
}
But I don't think it is right solution.
Alternative solution
using RetrySelect()
instead of Select
?
func (c *Client) writeLoop(wg *sync.WaitGroup) poisonReason {
...
...
- err := goselect.Select(1, rdfs, nil, nil, 50*time.Millisecond)
+ err := goselect.RetrySelect(1, rdfs, nil, nil, 50*time.Millisecond, 3, 50*time.Millisecond)
I think this interrupted system call
happen after golang/go#38033.
go1.13.15 => no interrupted system call
go1.14.11 => interrupted system call
error found
go1.15.4 => interrupted system call
error found
I'll make a PR