Printing multiple copies on remote printers

russell-cups at stuart.id.au russell-cups at stuart.id.au
Wed Dec 8 18:33:21 PST 2004


This bug has been observed in cups-1.1.20final+rc1 that
comes with Debian, and cups-1.1.22 compiled from source.

Remote printers are occassionally printing multiple
copies of jobs.  None of the jobs had the "copies"
option set.

The multiple copies was caused by two things:

1.  Made http_wait() did not handle EINTR.

2.  The wait in ipp_http_read was too short for connections
    that run over the internet.

Note:
    While both these bugs need to be fixed, neither completely
    solves the original multiple copies problem.  To solve
    that no data should be printed if there was a read or
    other error.

Patch that fixed the problems in cups-1.1.20final+rc1:

diff -Nur cupsys-1.1.20final+rc1.old/cups/http.c cupsys-1.1.20final+rc1/cups/http.c
--- cupsys-1.1.20final+rc1.old/cups/http.c      2004-05-28 04:17:54.000000000 +1000
+++ cupsys-1.1.20final+rc1/cups/http.c  2004-12-09 11:59:53.000000000 +1000
@@ -2000,6 +2000,9 @@
  * 'http_wait()' - Wait for data available on a connection.
  */

+#define        MSEC_2_TV(tv, msec)     (tv.tv_sec = msec / 1000, tv.tv_usec = msec % 1000 * 1000)
+#define        TV_2_MSEC(tv)           (tv.tv_sec * 1000 + tv.tv_usec / 1000)
+
 static int                             /* O - 1 if data is available, 0 otherwise */
 http_wait(http_t *http,                        /* I - HTTP data */
           int    msec)                 /* I - Milliseconds to wait */
@@ -2008,8 +2011,11 @@
   struct rlimit                limit;          /* Runtime limit */
 #endif /* !WIN32 */
   struct timeval       timeout;        /* Timeout */
+  struct timeval       start;          /* When we started waiting */
+  struct timeval       now;            /* The time now */
   int                  nfds;           /* Result from select() */
   int                  set_size;       /* Size of select set */
+  int                  delay;          /* Time remaining in milli seconds */


   DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec));
@@ -2069,19 +2075,32 @@
       return (0);
   }

-  FD_SET(http->fd, http->input_set);

-  if (msec >= 0)
-  {
-    timeout.tv_sec  = msec / 1000;
-    timeout.tv_usec = (msec % 1000) * 1000;
+  gettimeofday(&start, 0);
+  now = start;

-    nfds = select(http->fd + 1, http->input_set, NULL, NULL, &timeout);
-  }
-  else
-    nfds = select(http->fd + 1, http->input_set, NULL, NULL, NULL);
+  for (;;) {
+
+    FD_SET(http->fd, http->input_set);
+
+    delay = msec - (TV_2_MSEC(now) - TV_2_MSEC(start));
+
+    if (delay >= 0)
+    {
+      MSEC_2_TV(timeout, delay);
+      nfds = select(http->fd + 1, http->input_set, NULL, NULL, &timeout);
+    }
+    else
+      nfds = select(http->fd + 1, http->input_set, NULL, NULL, NULL);
+
+    FD_CLR(http->fd, http->input_set);
+
+    if (nfds >= 0 || errno != EINTR)
+      break;
+
+    gettimeofday(&now, 0);
+  }

-  FD_CLR(http->fd, http->input_set);

   return (nfds > 0);
 }
diff -Nur cupsys-1.1.20final+rc1.old/cups/ipp.c cupsys-1.1.20final+rc1/cups/ipp.c
--- cupsys-1.1.20final+rc1.old/cups/ipp.c       2004-02-26 06:14:51.000000000 +1000
+++ cupsys-1.1.20final+rc1/cups/ipp.c   2004-12-09 11:59:53.000000000 +1000
@@ -2501,7 +2501,12 @@
         * Wait up to 1 second for more data on non-blocking sockets...
        */

+       /*
+        * 1 second is far too short for a connection that runs over
+        * the internet.  2 minutes is a more reasonable value.
        if (!httpWait(http, 1000))
+        */
+       if (!httpWait(http, 2 * 60 * 1000))
        {
         /*
           * Signal no data...




More information about the cups mailing list