Univention Bugzilla – Bug 32532
udm not SIGPIPE safe
Last modified: 2024-01-10 17:03:44 CET
Something in UDM (or Python) is not prepared for the STDOUT pipe being closed early: # udm groups/group list | grep -Eq '^ (hosts|memberOf|users|groups):' close failed in file object destructor: Error in sys.excepthook: Original exception was: # strace -o /tmp/udm -f udm groups/group list | (dd bs=1 count=1 >/dev/null 2>&1) close failed in file object destructor: Error in sys.excepthook: Original exception was: # python -c 'print "*" * (1<<20)' | (dd bs=1 count=1 >/dev/null 2>&1) Traceback (most recent call last): File "<string>", line 1, in <module> IOError: [Errno 32] Broken pipe # cat /tmp/udm ... 30487 write(1, "=groups,dc=phahn,dc=dev\nARG: Non"..., 2964) = -1 EPIPE (Broken pipe) 30487 --- SIGPIPE (Broken pipe) @ 0 (0) --- 30487 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fc98fb9eff0}, {0x4daed0, [], SA_RESTORER, 0x7fc98fb9eff0}, 8) = 0 30487 write(2, "close failed in file object dest"..., 40) = 40 30487 write(2, "Error in sys.excepthook:\n", 25) = 25 30487 write(2, "\nOriginal exception was:\n", 25) = 25 30487 exit_group(0) = ?
# udm groups/group list | grep -Eq '^ (hosts|memberOf|users|groups):' Traceback (most recent call last): File "/usr/sbin/udm", line 195, in <module> main() File "/usr/sbin/udm", line 190, in main result = process_output(output, cmdfile) File "/usr/sbin/udm", line 146, in process_output print line IOError: [Errno 32] Broken pipe How should this be fixed? try-except around every print and exit(0) then?
*** Bug 48807 has been marked as a duplicate of this bug. ***
Patch in fbest/32532-udm-sigpipe-safe: diff --git a/management/univention-directory-manager-modules/univention-cli-client b/management/univention-directory-manager-modules/univention-cli-client index 9125ef7867..823c806ded 100755 --- a/management/univention-directory-manager-modules/univention-cli-client +++ b/management/univention-directory-manager-modules/univention-cli-client @@ -34,0 +35 @@ import socket +import signal @@ -185,0 +187 @@ def main(): +» signal.signal(signal.SIGPIPE, signal.SIG_DFL)
(In reply to Florian Best from comment #3) > +» signal.signal(signal.SIGPIPE, signal.SIG_DFL) Please beware of the dire consequences which might happen if you go that way as you change a fundamental assumption in all Python libraries: <https://docs.python.org/3/library/signal.html#note-on-sigpipe> For more issues with SIGPIPE in LDAP see <https://hutten.knut.univention.de/blog/unix-102-1-sigpipe/>. (In reply to Florian Best from comment #1) > How should this be fixed? try-except around every print and exit(0) then? NO: exit(0) != exit by SIGPIPE - the difference is IMPORTANT! Read <man:wait(2)> and <https://www.cons.org/cracauer/sigint.html> import os import signal import errno try: main() except IOError as ex: if ex.errno != errno.EPIPE: raise if False: # This is only needed if you prefer exit(1) devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) os.dup2(devnull, sys.stderr.fileno()) exit(1) else: # This will just kill python with SIGPIPE and STDOUT/STDERR will not be flushed signal.signal(signal.SIGPIPE, signal.SIG_DFL) os.kill(os.getpid(), signal.SIGPIPE) For testing: udm groups/group list | (dd bs=1 count=1 >/dev/null 2>&1) echo ${PIPESTATUS[@]} # 141 0 <man:bash(1)>: The return value of a simple command is ... 128+n if the command is terminated by signal n. <man:signal(7): SIGPIPE := 13
Okay, I see.
Also in our jenkins tests: Adding ZONE record "root@AutoTest091.local. 1 28800 10800 604800 108001 master091.AutoTest091.local." to zone 10.210... Traceback (most recent call last): File "/usr/sbin/univention-directory-manager", line 201, in <module> main() File "/usr/sbin/univention-directory-manager", line 196, in main result = process_output(output, cmdfile) File "/usr/sbin/univention-directory-manager", line 152, in process_output print line IOError: [Errno 32] Broken pipe
The Traceback in UCS 5.0: Traceback (most recent call last): File "/usr/sbin/univention-directory-manager", line 205, in <module> main() File "/usr/sbin/univention-directory-manager", line 200, in main result = process_output(output, cmdfile) File "/usr/sbin/univention-directory-manager", line 153, in process_output print(line) BrokenPipeError: [Errno 32] Broken pipe