Commit Graph

17 Commits

Author SHA1 Message Date
Taizeng Wu 5cd7f324f9 Use channel to implement a simple way to wait 2018-12-05 16:30:09 +08:00
Taizeng Wu 3a53acc96b Reimplement Wait method to make it can be called concurrently from multiple goroutines 2018-12-05 14:47:03 +08:00
Taizeng Wu fbf9e05c66 Add Wait method to detect underlying SFTP connection closed
Closes #278
2018-12-03 17:46:45 +08:00
John Eikenberry 22e9c1ccc0 set inflight chan buffer to 2 for deadlock
It is possible for dispatchRequest and broadcastErr to both send a
result down the inflight[] channel which has a buffer of 1, so would
work for one of them then block on the other. If broadcastErr went
first, then dispatchRequest would block causing the client to hang.
2018-02-06 16:43:44 -08:00
Pavel Borzenkov cb456b384c Fix race between client's close and write
After commit 506f3a7 which removed clientConn mutex around
conn.sendPacket, it is now possible for conn.Close and conn.Write to
race (https://travis-ci.org/pkg/sftp/jobs/219048782#L1838). The problem
is really hard to reproduce, but I believe this patch fixes it.

Now clientConn.Mutex protects 'inflight' map only, and conn.Mutex
serializes connection writes/close.

Signed-off-by: Pavel Borzenkov <pavel.borzenkov@gmail.com>
2017-04-08 20:29:37 -07:00
Pavel Borzenkov 506f3a7848 Fix deadlock when using Client + Service over io.Pipe
Client + Server might deadlock while being connected via io.Pipe with
high request concurrency. The scenario is as follows:

  - Server is trying to send reply to a previous client's packet and is
    waiting on Pipe's condvar for the client to read it:

 3  0x0000000000460e39 in sync.(*Cond).Wait
    at /usr/lib/go/src/sync/cond.go:57
 4  0x0000000000464519 in io.(*pipe).write
    at /usr/lib/go/src/io/pipe.go:90
 5  0x0000000000464a4c in io.(*PipeWriter).Write
    at /usr/lib/go/src/io/pipe.go:157
 6  0x00000000007a0b66 in go.(*struct { io.Reader; io.WriteCloser }).Write
    at <autogenerated>:246
 7  0x0000000000790cf6 in github.com/pkg/sftp.(*conn).Write
    at <autogenerated>:3
 8  0x000000000073a68d in github.com/pkg/sftp.sendPacket
    at ./packet.go:130
 9  0x000000000073338c in github.com/pkg/sftp.(*conn).sendPacket
    at ./conn.go:31
10  0x00000000007374b4 in github.com/pkg/sftp.(*packetManager).maybeSendPackets
    at ./packet-manager.go:87

  - Client is sending a new packet and is waiting on Pipe's condvar for
    the server to read it, while holding clientConn mutex:

 5  0x0000000000464a4c in io.(*PipeWriter).Write
    at /usr/lib/go/src/io/pipe.go:157
 6  0x0000000000790cf6 in github.com/pkg/sftp.(*conn).Write
    at <autogenerated>:3
 7  0x000000000073a68d in github.com/pkg/sftp.sendPacket
    at ./packet.go:130
 8  0x000000000073338c in github.com/pkg/sftp.(*conn).sendPacket
    at ./conn.go:31
 9  0x0000000000733bfb in github.com/pkg/sftp.(*clientConn).dispatchRequest
    at ./conn.go:105
10  0x0000000000733a0b in github.com/pkg/sftp.(*clientConn).sendPacket
    at ./conn.go:97

  - Client's receive loop is processing a reply from the server and is
    trying to acquire clientConn mutex:

4  0x000000000046108d in sync.(*Mutex).Lock
   at /usr/lib/go/src/sync/mutex.go:87
5  0x00000000007336cb in github.com/pkg/sftp.(*clientConn).recv
   at ./conn.go:69
6  0x000000000073350d in github.com/pkg/sftp.(*clientConn).loop
   at ./conn.go:49
7  0x000000000045ab51 in runtime.goexit
   at /usr/lib/go/src/runtime/asm_amd64.s:2197

In this scenario neither server nor client can progress. Fix this by
releasing clienConn mutex *before* trying to send the packet.

Signed-off-by: Pavel Borzenkov <pavel.borzenkov@gmail.com>
2017-04-05 14:15:57 -07:00
John Eikenberry 89c474ca1d new name for id (now ider) interface
more in line with go naming scheme for interfaces
better greppability
2017-03-23 16:15:04 -07:00
John Eikenberry 14f0a222dd Tests to replicate deadlock bug in Write/ReadFrom
github issue #145

A deadlock will occur in cases when using client.Write or client.ReadFrom,
it has 2 network issues in a row, and it is starting a new loop to send
more concurrent packets.
2017-02-13 00:32:33 -08:00
John Eikenberry bf1c2bb001 add lock on connection close to prevent race
Notably fixes occasional failures of TestServerRoughDisconnect due to
the race.

fixes #153
2017-01-31 16:24:31 -08:00
Dave Cheney 3a7eae5fbb Introduce serverConn (#119) 2016-06-15 21:08:29 +10:00
Dave Cheney ea1a7bcdfc conn: seperate io.Reader and io.WriteCloser (#118)
Reading and Writing are less coupled in the sftp client and server than
they may be over a traditional ReadWriter. This mirrors the full duplex
/ half close nature of a TCP connection.

In essence conn.Reader cannot be closed locally, it can only close in
response to the remote side using conn.WriteCloser.Close(), or a network
error, which is effectively the same thing.

Make this behaviour super clear by no longer smooshing the type into a
ReadWriteCloser.
2016-06-15 20:19:51 +10:00
Dave Cheney 9d52a809ce Always close client conn when clientConn.recv exits (#117)
If recv has exited then nobody will retrive the response, so
make sure we cannot send anything by shutting down the Write side of the
connection.
2016-06-15 20:04:26 +10:00
Dave Cheney 1a25dc501f rename sendRequest to sendPacket
clientConn.sendPacket now obscures clientConn.conn.sendPacket with a
diferent signature.
2016-06-15 18:57:05 +10:00
Dave Cheney 0847713e96 Migrate sendRequest to clientConn 2016-06-15 18:30:05 +10:00
Dave Cheney c91ab27c13 Move client.Close to clientConn.Close 2016-06-15 18:23:51 +10:00
Dave Cheney 9184483985 Introduce clientConn
clientConn embeds a conn and adds the basic loop/recv methods.
2016-06-15 18:08:04 +10:00
Dave Cheney 7d4fc94878 Introduce sftp.conn type to handle common send/recv behaviour (#113)
Introduce sftp.conn type to bind packet send/recv to a
io.ReadWriteCloser.
2016-06-15 11:50:02 +10:00