[prev in list] [next in list] [prev in thread] [next in thread]
List: cups-bugs
Subject: [cups.bugs] [MOD] STR #4187: _cupsConnect() can return cached http connection which is already unusa
From: Petr Cvachoucek <petr.cvachoucek () oracle ! com>
Date: 2012-09-12 8:01:49
Message-ID: 20120912080149.8202D3C6848F () dns ! easysw ! com
[Download RAW message or body]
DO NOT REPLY TO THIS MESSAGE. INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.
[STR New]
Hi all,
we have CUPS clients configured to print directly to remote CUPS server -
ie. we have /etc/cups/client.conf with ServerName pointing to our CUPS
server. And we see such unpleasant behavior:
1) first time the app does some request to libcups.so, the HTTP connection
is
created and used - all works ok. The HTTP connection is not closed but
cached
in _cupsGlobals.
2) The CUPS server has its timeout - if the connection is idle for some
time
(the default is 5 minutes), it closes it. This can be verified for
example
by netstat output on clients - the TCP connection state changes from
ESTABLISHED to CLOSE_WAIT.
3) Next time the app does some request to libcups.so, the cached HTTP
connection
is directly used - returned by _cupsConnect(). Request is sent (no
error
produced) and when reading response, the recv() call gets ECONNRESET
and
the request fails.
This is easy to reproduce. Start OpenOffice or LibreOffice,
open "File -> Printer Settings" dialog, close it and wait 5 minutes.
Then try to open it again - and the list of printers is empty.
The idea for fix is to check the TCP connection state in _cupsConnect()
and verify the connection is still in ESTABLISHED state. If its not then
close it - the _cupsConnect() will then re-create it.
I'm attaching the patch with the fix for Solaris - checking the TCP
connection
state is system-specific, so the real fix for upstream would have to add
the code for other supported platforms as well.
I understand the fix is not perfect - there's still chance for request to
fail
if the server closes the connection just after the client checks it. But
it is
not very invasive and improves the users experience a lot in this
scenario,
because otherwise this bug is hit always and is very annoying for users.
Link: http://www.cups.org/str.php?L4187
Version: 1.6-current
["cupsconnect.patch" (text/plain)]
diff -Naur cups-1.6svn-r10486.orig/cups/request.c cups-1.6svn-r10486/cups/request.c
--- cups-1.6svn-r10486.orig/cups/request.c 2012-05-12 02:07:16.000000000 +0200
+++ cups-1.6svn-r10486/cups/request.c 2012-09-12 09:16:21.888777664 +0200
@@ -46,7 +46,9 @@
#ifndef O_BINARY
# define O_BINARY 0
#endif /* O_BINARY */
-
+#if defined(__sun)
+#include <inet/tcp.h> /* need this for TCPS_ESTABLISHED ... */
+#endif
/*
* 'cupsDoFileRequest()' - Do an IPP request with a file.
@@ -1000,6 +1002,38 @@
}
}
+#if defined(__sun)
+ /*
+ * Check the connection state.
+ * If the connection wasn't used for some time, the server could close it.
+ * The socket state would change to CLOSE_WAIT in such case.
+ */
+ if (cg->http)
+ {
+ struct tcp_info tcpi;
+ socklen_t len = sizeof(tcpi);
+ memset(&tcpi, 0, sizeof(tcpi));
+
+ /*
+ * Get TCP connection info.
+ */
+ if (getsockopt(cg->http->fd, IPPROTO_TCP, TCP_INFO, &tcpi, &len) == 0)
+ {
+ /*
+ * Successfully got TCP connection state. Check it.
+ */
+ if (tcpi.tcpi_state != TCPS_ESTABLISHED)
+ {
+ /*
+ * Need to close the current connection.
+ */
+ httpClose(cg->http);
+ cg->http = NULL;
+ }
+ }
+ }
+#endif
+
/*
* (Re)connect as needed...
*/
_______________________________________________
cups-bugs mailing list
cups-bugs@easysw.com
http://lists.easysw.com/mailman/listinfo/cups-bugs
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic