You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

42 lines
1.8 KiB

  1. commit 487b38e86c08431bc5f48aac72c8d753ee23cb03
  2. Author: Willy Tarreau <w@1wt.eu>
  3. Date: Fri Jul 26 15:10:39 2019 +0200
  4. BUG/MINOR: log: make sure writev() is not interrupted on a file output
  5. Since 1.9 we support sending logs to various non-blocking outputs like
  6. stdou/stderr or flies, by using writev() which guarantees that it only
  7. returns after having written everything or nothing. However the syscall
  8. may be interrupted while doing so, and this is visible when writing to
  9. a tty during debug sessions, as some logs occasionally appear interleaved
  10. if an xterm or SSH connection is not very fast. Performance here is not a
  11. critical concern, log correctness is. Let's simply take the logger's lock
  12. around the writev() call to prevent multiple senders from stepping onto
  13. each other's toes.
  14. This may be backported to 2.0 and 1.9.
  15. (cherry picked from commit 9fbcb7e2e9c32659ab11927394fec2e160be2d0b)
  16. Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
  17. diff --git a/src/log.c b/src/log.c
  18. index ef999d13..99f185e4 100644
  19. --- a/src/log.c
  20. +++ b/src/log.c
  21. @@ -1672,8 +1672,15 @@ send:
  22. iovec[7].iov_len = 1;
  23. if (logsrv->addr.ss_family == AF_UNSPEC) {
  24. - /* the target is a direct file descriptor */
  25. + /* the target is a direct file descriptor. While writev() guarantees
  26. + * to write everything, it doesn't guarantee that it will not be
  27. + * interrupted while doing so. This occasionally results in interleaved
  28. + * messages when the output is a tty, hence the lock. There's no real
  29. + * performance concern here for such type of output.
  30. + */
  31. + HA_SPIN_LOCK(LOGSRV_LOCK, &logsrv->lock);
  32. sent = writev(*plogfd, iovec, 8);
  33. + HA_SPIN_UNLOCK(LOGSRV_LOCK, &logsrv->lock);
  34. }
  35. else {
  36. msghdr.msg_name = (struct sockaddr *)&logsrv->addr;