Skip to content

Commit 39e65ab

Browse files
committed
Start rsync daemon in the foreground to prevent zombie processes
1 parent 50f1f6e commit 39e65ab

File tree

1 file changed

+47
-18
lines changed

1 file changed

+47
-18
lines changed

pkg/cmd/cli/cmd/rsync/copyrsyncd.go

+47-18
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77
"io"
8+
"io/ioutil"
89
"math/rand"
910
"net"
1011
"strconv"
@@ -28,16 +29,26 @@ const (
2829
// The output of the script is the name of a file containing the PID for the started daemon
2930
startDaemonScript = `set -e
3031
TMPDIR=${TMPDIR:-/tmp}
31-
CONFIGFILE=$(mktemp 2> /dev/null || (echo -n "" > ${TMPDIR}/%[1]s && echo ${TMPDIR}/%[1]s))
32-
PIDFILE=$(mktemp 2> /dev/null || (echo -n "" > ${TMPDIR}/%[2]s && echo ${TMPDIR}/%[2]s))
32+
CONFIGFILE=$(echo -n "" > ${TMPDIR}/%[1]s && echo ${TMPDIR}/%[1]s)
33+
PIDFILE=$(echo -n "" > ${TMPDIR}/%[2]s && echo ${TMPDIR}/%[2]s)
3334
rm $PIDFILE
3435
printf "pid file = ${PIDFILE}\n[root]\n path = /\n use chroot = no\n read only = no" > $CONFIGFILE
35-
rsync --daemon --config=${CONFIGFILE} --port=%[3]d
36-
echo ${PIDFILE}
36+
rsync --no-detach --daemon --config=${CONFIGFILE} --port=%[3]d
3737
`
38-
portRangeFrom = 30000
39-
portRangeTo = 60000
40-
remoteLabel = "root"
38+
killDaemonScript = `set -e
39+
TMPDIR=${TMPDIR:-/tmp}
40+
PIDFILE=${TMPDIR}/%[1]s
41+
kill $(cat ${PIDFILE})
42+
`
43+
checkDaemonScript = `set -e
44+
TMPDIR=${TMPDIR:-/tmp}
45+
PIDFILE=${TMPDIR}/%[1]s
46+
ls ${PIDFILE}
47+
`
48+
portRangeFrom = 30000
49+
portRangeTo = 60000
50+
remoteLabel = "root"
51+
RsyncDaemonStartTimeOut = 10 * time.Second
4152
)
4253

4354
var (
@@ -152,26 +163,44 @@ func (s *rsyncDaemonStrategy) startRemoteDaemon() error {
152163
}
153164
cmdOut := &bytes.Buffer{}
154165
cmdErr := &bytes.Buffer{}
155-
cmdIn := bytes.NewBufferString(fmt.Sprintf(startDaemonScript, krand.String(32), krand.String(32), port))
156-
err = s.RemoteExecutor.Execute([]string{"sh"}, cmdIn, cmdOut, cmdErr)
157-
if err != nil {
158-
glog.V(1).Infof("Error starting rsync daemon: %v. Out: %s, Err: %s\n", err, cmdOut.String(), cmdErr.String())
159-
// Determine whether rsync is present in the container
160-
if checkRsync(s.RemoteExecutor) != nil {
161-
return strategySetupError("rsync not available in container")
166+
pidFile := krand.String(32)
167+
configFile := krand.String(32)
168+
cmdIn := bytes.NewBufferString(fmt.Sprintf(startDaemonScript, configFile, pidFile, port))
169+
daemonErr := make(chan error, 1)
170+
go func() {
171+
err = s.RemoteExecutor.Execute([]string{"sh"}, cmdIn, cmdOut, cmdErr)
172+
if err != nil {
173+
daemonErr <- fmt.Errorf("error starting rsync daemon: %v\nOut: %s\nErr: %s\n", err, cmdOut.String(), cmdErr.String())
162174
}
163-
return err
175+
}()
176+
// Wait until a pid file is present or an error has occurred
177+
checkScript := bytes.NewBufferString(fmt.Sprintf(checkDaemonScript, pidFile))
178+
startTime := time.Now()
179+
for {
180+
if time.Since(startTime) > RsyncDaemonStartTimeOut {
181+
return fmt.Errorf("Timed out waiting for rsync daemon to start")
182+
}
183+
checkScript.Reset()
184+
err = s.RemoteExecutor.Execute([]string{"sh"}, checkScript, ioutil.Discard, ioutil.Discard)
185+
if err == nil {
186+
break
187+
}
188+
if len(daemonErr) > 0 {
189+
return <-daemonErr
190+
}
191+
time.Sleep(100 * time.Millisecond)
164192
}
165193
s.daemonPort = port
166-
s.daemonPIDFile = strings.TrimSpace(cmdOut.String())
194+
s.daemonPIDFile = pidFile
167195
return nil
168196
}
169197

170198
func (s *rsyncDaemonStrategy) killRemoteDaemon() error {
171-
cmd := []string{"sh", "-c", fmt.Sprintf("kill $(cat %s)", s.daemonPIDFile)}
199+
cmd := []string{"sh"}
200+
cmdIn := bytes.NewBufferString(fmt.Sprintf(killDaemonScript, s.daemonPIDFile))
172201
cmdOut := &bytes.Buffer{}
173202
cmdErr := &bytes.Buffer{}
174-
err := s.RemoteExecutor.Execute(cmd, nil, cmdOut, cmdErr)
203+
err := s.RemoteExecutor.Execute(cmd, cmdIn, cmdOut, cmdErr)
175204
if err != nil {
176205
glog.V(1).Infof("Error killing rsync daemon: %v. Out: %s, Err: %s\n", err, cmdOut.String(), cmdErr.String())
177206
}

0 commit comments

Comments
 (0)