Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

usb backend hangs in cupsBackChannelWrite #1705

Closed
michaelrsweet opened this issue May 18, 2006 · 13 comments
Closed

usb backend hangs in cupsBackChannelWrite #1705

michaelrsweet opened this issue May 18, 2006 · 13 comments
Milestone

Comments

@michaelrsweet
Copy link
Collaborator

Version: 1.2.0
CUPS.org User: twaugh.redhat

RH bugzilla bug #192034:

https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=192034

describes a busy loop in the 'usb' backend when printing to a Canon iP4000 USB printer. The problem seems to be that the printer always returns an IEEE 1284 Device ID when asked for data, and this seems to fill a buffer (perhaps the pipe buffer -- does cupsd ever read back_pipe?).

The result is that the 'usb' backend gets stuck looping round select() for write-ready in cupsBackChannelWrite().

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: twaugh.redhat

The attached patch, cups-str1705.patch, fixes the problem for the reporter. It disables the back-channel data reading altogether.

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: mike

Yeah, that's definitely not the patch we want to use as a final fix, though... ;)

cupsBackChannelWrite() shouldn't block, so I'll delve into that code to see what's up...

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: mike

Try the attached patch instead - it makes the backchannel pipe non-blocking so that cupsBackChannelWrite() won't block in the middle of a write().

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: twaugh.redhat

It isn't blocking in write() -- it's getting EAGAIN. But then it goes back round the loop, times out in select() waiting for write-ready (the pipe is full so it's never ready to write) and then falls through and tries to write() again anyway.

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: mike

OK, the attached patch should take care of EAGAIN...

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: twaugh.redhat

Great. There's still the issue of the odd behaviour of this particular printer though. It seems to offer a 187-byte Device ID each time we read from it -- which is presumably once every time around the write loop.

So once the pipe buffer does get filled up (the scheduler isn't reading from it), we'll be waiting for 1s every time we try to pass the back-channel data back to the scheduler.

That's going to be really slow for writing a large file!

I think we need to catch this weird behaviour and turn off back-channel data reading when we see it. Perhaps if we get the same data a few times in a row or something?

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: mike

Yeah, I'm thinking of adding a backchannel option in the URI and advertising the "backchannel=off" option for Canon printers...

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: mike

OK, this last patch adds a check for Canon printers and disables the backchannel read's and select's.

@michaelrsweet
Copy link
Collaborator Author

CUPS.org User: mike

Fixed in Subversion repository.

@michaelrsweet
Copy link
Collaborator Author

"cups-str1705.patch":

--- cups-1.2.x/backend/usb-unix.c.str1705 2006-05-18 18:12:40.000000000 +0100
+++ cups-1.2.x/backend/usb-unix.c 2006-05-18 18:13:38.000000000 +0100
@@ -238,7 +238,7 @@
do
{
FD_ZERO(&input);

  • FD_SET(fd, &input);
    
  • // FD_SET(fd, &input); // disable back-channel data (see STR #1705)
    
    FD_ZERO(&output);
    FD_SET(fd, &output);
    }

@michaelrsweet
Copy link
Collaborator Author

"str1705.patch":

Index: scheduler/job.c

--- scheduler/job.c (revision 5538)
+++ scheduler/job.c (working copy)
@@ -2632,8 +2632,23 @@

if (job->current_file == 0)
{

  • /*
  • * Set the processing time...
  • */

set_time(job, "time-at-processing");
+

  • /*
  • * Create the backchannel pipes and make them non-blocking...
  • */

cupsdOpenPipe(job->back_pipes);
+

  • fcntl(job->back_pipes[0], F_SETFL,

  •      fcntl(job->back_pipes[0], F_GETFL) | O_NONBLOCK);
    
  • fcntl(job->back_pipes[1], F_SETFL,

  •      fcntl(job->back_pipes[1], F_GETFL) | O_NONBLOCK);
    

    }

    /*

@michaelrsweet
Copy link
Collaborator Author

"str1705p2.patch":

Index: backchannel.c

--- backchannel.c (revision 5547)
+++ backchannel.c (working copy)
@@ -161,7 +161,7 @@
* Write error - abort on fatal errors...
*/

  •  if (errno != EINTR && errno != EAGAIN)
    
  •  if (errno != EINTR)
     return (-1);
    
    }
    else

@michaelrsweet
Copy link
Collaborator Author

"str1705p3.patch":

Index: usb-unix.c

--- usb-unix.c (revision 5551)
+++ usb-unix.c (working copy)
@@ -60,6 +60,7 @@
int argc, /* I - Number of command-line arguments (6 or 7) /
char *argv[]) /
I - Command-line arguments */
{

  • int usebc; /* Use backchannel path? /
    int fd; /
    USB device /
    int rbytes; /
    Number of bytes read /
    int wbytes; /
    Number of bytes written */
    @@ -83,6 +84,14 @@
    (void)argv;

/*

  • * Disable backchannel data when printing to Canon USB printers - apparently
  • * Canon printers will return the IEEE-1284 device ID over and over and over
  • * when they get a read request...
  • */
  • usebc = strcasecmp(hostname, "Canon") != 0;
  • /*
    • Open the USB port device...
      */

@@ -238,7 +247,9 @@
do
{
FD_ZERO(&input);

  • FD_SET(fd, &input);
    
  • if (usebc)
    
  •   FD_SET(fd, &input);
    
    • FD_ZERO(&output);
      FD_SET(fd, &output);
      }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant