Sophie

Sophie

distrib > Mageia > cauldron > i586 > by-pkgid > 0b68e0a10a18bb19ea7797c095fdd9a9 > files > 2

haproxy-2.8.9-1.mga10.src.rpm

From: Raphaƫl Gertz <haproxy@rapsys.eu>
Date: Tue Oct 31 19:00:00 CET 2023
Subject: [PATCH] Keep O_APPEND flag to prevent log corruption by haproxy when using stdout

This fix prevent the flag clear of all other O_* flags to drop O_APPEND as well when setting O_NONBLOCK.

It allows to redirect haproxy stdout log to a file without corruption.


1/ Bug configuration:

global
    log stdout format short daemon


2/ Test case:

$ echo 'line1\nline2' > stdout.log; haproxy -f haproxy.conf >> stdout.log


3/ Corrupted result:

<6> [...]


4/ Result after patch:

line1
line2
<6> [...]


5/ Donation

Like my work, request a feature or want to do a donation ?

You may send me a beer, tea, coffee or more via PayPal at paypal@rapsys.eu via:
https://www.paypal.com/myaccount/transfer/homepage/pay


diff -urNp haproxy-2.8.3.orig/include/haproxy/fd.h haproxy-2.8.3/include/haproxy/fd.h
--- haproxy-2.8.3.orig/include/haproxy/fd.h	2023-09-07 11:32:42.000000000 +0200
+++ haproxy-2.8.3/include/haproxy/fd.h	2023-10-31 18:30:17.592943791 +0100
@@ -59,6 +59,12 @@ extern volatile int ha_used_fds; // Numb
 void fd_delete(int fd);
 void _fd_delete_orphan(int fd);
 
+/* makes the new fd non-blocking and clears all other O_* flags
+ * except extra; this is meant to be used on new FDs.
+ * Returns -1 on failure.
+ */
+int fd_set_nonblock_extra(int fd, uint extra);
+
 /* makes the new fd non-blocking and clears all other O_* flags;
  * this is meant to be used on new FDs. Returns -1 on failure.
  */
diff -urNp haproxy-2.8.3.orig/src/fd.c haproxy-2.8.3/src/fd.c
--- haproxy-2.8.3.orig/src/fd.c	2023-09-07 11:32:42.000000000 +0200
+++ haproxy-2.8.3/src/fd.c	2023-10-31 18:46:31.821142586 +0100
@@ -436,6 +436,18 @@ void fd_delete(int fd)
 	}
 }
 
+/* makes the new fd non-blocking and clears all other O_* flags except extra;
+ * this is meant to be used on new FDs. Returns -1 on failure. The result is
+ * disguised at the end because some callers need to be able to ignore it
+ * regardless of the libc attributes.
+ */
+int fd_set_nonblock_extra(int fd, uint extra)
+{
+	int ret = fcntl(fd, F_SETFL, extra|O_NONBLOCK);
+
+	return DISGUISE(ret);
+}
+
 /* makes the new fd non-blocking and clears all other O_* flags; this is meant
  * to be used on new FDs. Returns -1 on failure. The result is disguised at the
  * end because some callers need to be able to ignore it regardless of the libc
@@ -443,7 +455,7 @@ void fd_delete(int fd)
  */
 int fd_set_nonblock(int fd)
 {
-	int ret = fcntl(fd, F_SETFL, O_NONBLOCK);
+	int ret = fd_set_nonblock_extra(fd, 0);
 
 	return DISGUISE(ret);
 }
@@ -921,8 +933,12 @@ ssize_t fd_write_frag_line(int fd, size_
 
 	if (unlikely(!(fdtab[fd].state & FD_INITIALIZED))) {
 		HA_ATOMIC_OR(&fdtab[fd].state, FD_INITIALIZED);
-		if (!isatty(fd))
-			fd_set_nonblock(fd);
+		if (!isatty(fd)) {
+			/* Retriev fd mode */
+			uint mode = fcntl(fd, F_GETFL);
+			/* Pass O_APPEND */
+			fd_set_nonblock_extra(fd, mode & O_APPEND);
+		}
 	}
 	sent = writev(fd, iovec, vec);
 	HA_ATOMIC_BTR(&fdtab[fd].state, FD_EXCL_SYSCALL_BIT);