mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-09-14 14:18:23 -04:00
* daemon: require IP stream for inetd mode * daemon: preserve bidirectional stdio mode * daemon: honour explicit no-detach mode * daemon: preserve inetd socket detection * ci: fix daemon socket checks
75 lines
2.1 KiB
Python
75 lines
2.1 KiB
Python
"""Launch one rsync daemon session over a loopback TCP connection."""
|
|
|
|
import socket
|
|
import subprocess
|
|
|
|
import rsync_proto as rp
|
|
|
|
from rsyncfns import rsync_argv
|
|
|
|
|
|
def _client_for_socket(sock, timeout=10):
|
|
client = object.__new__(rp.DaemonClient)
|
|
client.sock = sock
|
|
client.sock.settimeout(timeout)
|
|
client.protocol = rp.DEFAULT_PROTOCOL
|
|
client.compat_flags = None
|
|
client.seed = None
|
|
client.xfer_sum_len = 16
|
|
client._rbuf = b''
|
|
client._ndx_prev_positive = -1
|
|
client._ndx_prev_negative = 1
|
|
client._mux_in = b''
|
|
client._r_ndx_prev_positive = -1
|
|
client._r_ndx_prev_negative = 1
|
|
client.messages = []
|
|
return client
|
|
|
|
|
|
def start_stdio_daemon(conf, timeout=10, env=None):
|
|
"""Return ``(DaemonClient, Popen)`` for one daemon connection."""
|
|
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
parent = None
|
|
try:
|
|
listener.bind(('127.0.0.1', 0))
|
|
listener.listen(1)
|
|
parent = socket.create_connection(listener.getsockname(), timeout)
|
|
child, _ = listener.accept()
|
|
except OSError:
|
|
if parent is not None:
|
|
parent.close()
|
|
raise
|
|
finally:
|
|
listener.close()
|
|
try:
|
|
proc = subprocess.Popen(
|
|
rsync_argv('--daemon', '--no-detach', f'--config={conf}'),
|
|
stdin=child.fileno(), stdout=child.fileno(),
|
|
stderr=subprocess.PIPE, close_fds=True, env=env,
|
|
)
|
|
except Exception:
|
|
parent.close()
|
|
child.close()
|
|
raise
|
|
child.close()
|
|
return _client_for_socket(parent, timeout), proc
|
|
|
|
|
|
def finish_stdio_daemon(client, proc, timeout=5):
|
|
"""Close a test session and return the daemon's stderr text."""
|
|
try:
|
|
client.drain(timeout=0.25)
|
|
except OSError:
|
|
pass
|
|
client.close()
|
|
try:
|
|
proc.wait(timeout=timeout)
|
|
except subprocess.TimeoutExpired:
|
|
proc.terminate()
|
|
try:
|
|
proc.wait(timeout=timeout)
|
|
except subprocess.TimeoutExpired:
|
|
proc.kill()
|
|
proc.wait(timeout=timeout)
|
|
return proc.stderr.read().decode('utf-8', 'replace') if proc.stderr else ''
|