mirror of
https://github.com/go-gitea/gitea.git
synced 2026-11-09 17:37:20 -06:00
fix(ssh): let pushes finish when the client disconnects early (#40105)
With the built-in SSH server, closing the client connection cancelled the `gitea serv` process tree. go-git based clients close it right after the push report, so post-receive was killed and branches, pull requests, webhooks and Actions were not updated. The command now runs under the server's hammer context like with OpenSSH, where it ends once its pipes close or at shutdown.
This commit is contained in:
@@ -28,7 +28,6 @@ type sshServer struct {
|
|||||||
type sshSession struct {
|
type sshSession struct {
|
||||||
gossh.Channel
|
gossh.Channel
|
||||||
conn *gossh.ServerConn
|
conn *gossh.ServerConn
|
||||||
ctx context.Context
|
|
||||||
rawCmd string
|
rawCmd string
|
||||||
env []string
|
env []string
|
||||||
}
|
}
|
||||||
@@ -86,10 +85,7 @@ func (srv *sshServer) serve(listener net.Listener) error {
|
|||||||
func (srv *sshServer) handleConn(netConn net.Conn) {
|
func (srv *sshServer) handleConn(netConn net.Conn) {
|
||||||
defer netConn.Close()
|
defer netConn.Close()
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(graceful.GetManager().HammerContext())
|
sshConn, sshChannels, sshReqs, err := gossh.NewServerConn(netConn, srv.newServerConfig(graceful.GetManager().HammerContext()))
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
sshConn, sshChannels, sshReqs, err := gossh.NewServerConn(netConn, srv.newServerConfig(ctx))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// OpenSSH's logs are something like:
|
// OpenSSH's logs are something like:
|
||||||
// * disconnect without sending anything: "Connection closed by 1.2.3.4 port 5678"
|
// * disconnect without sending anything: "Connection closed by 1.2.3.4 port 5678"
|
||||||
@@ -107,11 +103,11 @@ func (srv *sshServer) handleConn(netConn net.Conn) {
|
|||||||
_ = newChan.Reject(gossh.UnknownChannelType, "unsupported channel type")
|
_ = newChan.Reject(gossh.UnknownChannelType, "unsupported channel type")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go handleSessionChannel(ctx, sshConn, newChan)
|
go handleSessionChannel(sshConn, newChan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSessionChannel(ctx context.Context, conn *gossh.ServerConn, newChan gossh.NewChannel) {
|
func handleSessionChannel(conn *gossh.ServerConn, newChan gossh.NewChannel) {
|
||||||
channel, reqs, err := newChan.Accept()
|
channel, reqs, err := newChan.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("SSH: Accept session channel: %v", err)
|
log.Error("SSH: Accept session channel: %v", err)
|
||||||
@@ -119,7 +115,7 @@ func handleSessionChannel(ctx context.Context, conn *gossh.ServerConn, newChan g
|
|||||||
}
|
}
|
||||||
defer channel.Close()
|
defer channel.Close()
|
||||||
|
|
||||||
session := &sshSession{Channel: channel, conn: conn, ctx: ctx}
|
session := &sshSession{Channel: channel, conn: conn}
|
||||||
for req := range reqs {
|
for req := range reqs {
|
||||||
switch req.Type {
|
switch req.Type {
|
||||||
case "env":
|
case "env":
|
||||||
|
|||||||
@@ -64,9 +64,6 @@ func sessionHandler(session *sshSession) int {
|
|||||||
args := []string{"--config=" + setting.CustomConf, "serv", "key-" + keyID}
|
args := []string{"--config=" + setting.CustomConf, "serv", "key-" + keyID}
|
||||||
log.Trace("SSH: Arguments: %v", args)
|
log.Trace("SSH: Arguments: %v", args)
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(session.ctx)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
gitProtocol := ""
|
gitProtocol := ""
|
||||||
for _, env := range session.env {
|
for _, env := range session.env {
|
||||||
if strings.HasPrefix(env, "GIT_PROTOCOL=") {
|
if strings.HasPrefix(env, "GIT_PROTOCOL=") {
|
||||||
@@ -75,7 +72,7 @@ func sessionHandler(session *sshSession) int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := process.CommandContext(ctx, setting.AppPath, args...)
|
cmd := process.CommandContext(graceful.GetManager().HammerContext(), setting.AppPath, args...)
|
||||||
cmd.Env = append(
|
cmd.Env = append(
|
||||||
os.Environ(),
|
os.Environ(),
|
||||||
"SSH_ORIGINAL_COMMAND="+session.rawCmd,
|
"SSH_ORIGINAL_COMMAND="+session.rawCmd,
|
||||||
|
|||||||
Reference in New Issue
Block a user