From c2f26288da893227f845915c15fa613e99630427 Mon Sep 17 00:00:00 2001 From: Zdenek Dohnal Date: Fri, 15 Dec 2023 11:20:07 +0100 Subject: [PATCH] 2254578 - cupsGetJobs() failes because libcups fails to connect to domain socket --- ...-Check-for-error-if-POLLHUP-is-in-va.patch | 76 +++++++++++++++++++ cups.spec | 9 ++- 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 0001-httpAddrConnect2-Check-for-error-if-POLLHUP-is-in-va.patch diff --git a/0001-httpAddrConnect2-Check-for-error-if-POLLHUP-is-in-va.patch b/0001-httpAddrConnect2-Check-for-error-if-POLLHUP-is-in-va.patch new file mode 100644 index 0000000..f5a106c --- /dev/null +++ b/0001-httpAddrConnect2-Check-for-error-if-POLLHUP-is-in-va.patch @@ -0,0 +1,76 @@ +From e0c31f4794ef637b74b0a0074364ff407ca40d5a Mon Sep 17 00:00:00 2001 +From: Zdenek Dohnal +Date: Fri, 15 Dec 2023 10:59:54 +0100 +Subject: [PATCH] httpAddrConnect2: Check for error if POLLHUP is in valid + revents + +Some Linux kernel versions put POLLOUT|POLLHUP into revents when client tries to connect with httpAddrConnect2(), which makes the connection fail. +Let's check the option SO_ERROR before scratching the attempt - if there is no error, remove POLLHUP from revents. + +I've re-purposed previously Solaris-only code to be used everywhere if the conditions are met - this should prevent bigger delays than necessary. + +Slightly different issue than #827, but with similar symptoms (kernel sending POLLOUT|POLLHUP). +--- + CHANGES.md | 2 ++ + cups/http-addrlist.c | 43 ++++++++++++++++++++++++++++++------------- + 2 files changed, 32 insertions(+), 13 deletions(-) + +diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c +index 198d073d0..cffcf184c 100644 +--- a/cups/http-addrlist.c ++++ b/cups/http-addrlist.c +@@ -318,21 +318,38 @@ httpAddrConnect2( + { + # ifdef HAVE_POLL + DEBUG_printf(("pfds[%d].revents=%x\n", i, pfds[i].revents)); +-# ifdef __sun +- // Solaris connect runs asynchronously returning EINPROGRESS. Following +- // poll() does not detect the socket is not connected and returns +- // POLLIN|POLLOUT. Check the connection status and update error flag. +- int sres, serr; +- socklen_t slen = sizeof(serr); +- sres = getsockopt(fds[i], SOL_SOCKET, SO_ERROR, &serr, &slen); +- if (sres || serr) ++ ++# ifdef _WIN32 ++ if (((WSAGetLastError() == WSAEINPROGRESS) && (pfds[i].revents & POLLIN) && (pfds[i].revents & POLLOUT)) || ++ ((pfds[i].revents & POLLHUP) && (pfds[i].revents & (POLLIN|POLLOUT)))) ++# else ++ if (((errno == EINPROGRESS) && (pfds[i].revents & POLLIN) && (pfds[i].revents & POLLOUT)) || ++ ((pfds[i].revents & POLLHUP) && (pfds[i].revents & (POLLIN|POLLOUT)))) ++# endif /* _WIN32 */ + { +- pfds[i].revents |= POLLERR; +-# ifdef DEBUG +- DEBUG_printf(("1httpAddrConnect2: getsockopt returned: %d with error: %s", sres, strerror(serr))); +-# endif ++ // Some systems generate POLLIN or POLLOUT together with POLLHUP when doing ++ // asynchronous connections. The solution seems to be to use getsockopt to ++ // check the SO_ERROR value and ignore the POLLHUP if there is no error or ++ // the error is EINPROGRESS. ++ ++ int sres, /* Return value from getsockopt() - 0, or -1 if error */ ++ serr; /* Option SO_ERROR value */ ++ socklen_t slen = sizeof(serr); /* Option value size */ ++ ++ sres = getsockopt(fds[i], SOL_SOCKET, SO_ERROR, &serr, &slen); ++ ++ if (sres || serr) ++ { ++ pfds[i].revents |= POLLERR; ++# ifdef DEBUG ++ DEBUG_printf(("1httpAddrConnect2: getsockopt returned: %d with error: %s", sres, strerror(serr))); ++# endif ++ } ++ else if (pfds[i].revents && (pfds[i].revents & POLLHUP) && (pfds[i].revents & (POLLIN | POLLOUT))) ++ { ++ pfds[i].revents &= ~POLLHUP; ++ } + } +-# endif // __sun + + + if (pfds[i].revents && !(pfds[i].revents & (POLLERR | POLLHUP))) +-- +2.43.0 + diff --git a/cups.spec b/cups.spec index 3d79fa6..b932cce 100644 --- a/cups.spec +++ b/cups.spec @@ -22,7 +22,7 @@ Summary: CUPS printing system Name: cups Epoch: 1 Version: 2.4.7 -Release: 4%{?dist} +Release: 5%{?dist} # backend/failover.c - BSD-3-Clause # cups/md5* - Zlib # scheduler/colorman.c - Apache-2.0 WITH LLVM-exception AND BSD-2-Clause @@ -91,6 +91,8 @@ Patch1001: 0001-Use-purge-job-instead-of-purge-jobs-when-canceling-a.patch Patch1002: cups-colorman-leak.patch # https://github.com/OpenPrinting/cups/pull/813/ Patch1003: cups-unload-job-leak.patch +# https://github.com/OpenPrinting/cups/pull/839 +Patch1004: 0001-httpAddrConnect2-Check-for-error-if-POLLHUP-is-in-va.patch ##### Patches removed because IMHO they aren't no longer needed @@ -325,6 +327,8 @@ to CUPS daemon. This solution will substitute printer drivers and raw queues in %patch -P 1002 -p1 -b .colorman # https://github.com/OpenPrinting/cups/pull/813/ %patch -P 1003 -p1 -b .unloadjob +# https://github.com/OpenPrinting/cups/pull/839 +%patch -P 1004 -p1 -b .httpaddrconnect-pollhup %if %{lspp} @@ -797,6 +801,9 @@ rm -f %{cups_serverbin}/backend/smb %{_mandir}/man7/ippeveps.7.gz %changelog +* Fri Dec 15 2023 Zdenek Dohnal - 1:2.4.7-5 +- 2254578 - cupsGetJobs() failes because libcups fails to connect to domain socket + * Mon Dec 11 2023 Zdenek Dohnal - 1:2.4.7-4 - make a weak dep on cups-browsed to prevent cups-browsed disappearing during upgrade