I’ve got a go app that downloads files using github.com/jlaffaye/ftp which is a library that implements File Transfer Protocol (FTP)
Defined a struct with an FTP connection
type Client struct {
conn *ftp.ServerConn
sync.Mutex
}
I have a global client
var cli *Client = nil
Which I then initialize and assign to the global variable to be used later
conn, err := ftp.Dial(cfg.Host+cfg.Port, ftp.DialWithContext(ctx))
if err != nil {
return fmt.Errorf("ftp dial error: %v", err)
}
err = conn.Login(cfg.Username, pwd)
if err != nil {
return fmt.Errorf("ftp login error: %v", err)
}
c := &Client{}
c.Lock()
c.conn = conn
cli = c
c.Unlock()
I’ve got a http handler that takes the conn field from the Client struct and calls
fileNames, err := conn.NameList(".")
if err != nil {
return err
}
Most of the time, the application fails on the call to conn.NameList(".")
with error
write tcp xxx.xxx.xx.x:48572-\u003exx.xxx.xxx.xxx:21: write: broken pipe
And sometimes
write tcp xxx.xxx.xx.xx:63037-\u003exx.xxx.xxx.xxx:21: wsasend: An established connection was aborted by the software in your host machine
I don’t close the connection prematurely.
Does anyone have an idea on why this is happening? Or maybe you could recommend a better library that uses FTP?
As per a question if multiple services are running at the same time, and if it’s conccurently safe.
When a process is running, another can’t run until setIsRunning(false) is called
func (s *Service) setIsRunning(b bool) error {
mu := &sync.Mutex{}
mu.Lock()
defer mu.Unlock()
if b && s.isRunning {
return errors.New("already running")
}
s.isRunning = b
return nil
}
An attempt to call that handler while its running will yield
"error":"already running"
Also I use mutex locks while reading from the global Client
like such
cli.Lock()
conn = cli.conn
cli.Unlock()