NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/41651: cups doesn't print any more



>Number:         41651
>Category:       kern
>Synopsis:       cups doesn't print any more
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Jun 30 10:50:00 +0000 2009
>Originator:     Wolfgang Solfrank
>Release:        NetBSD 5.99.14
>Organization:
        
>Environment:
        
        
System: NetBSD ws.solfrank.net 5.99.14 NetBSD 5.99.14 (ws) #1: Mon Jun 29 
22:14:42 MEST 2009 
ws%ws.solfrank.net@localhost:/src/obj/sys/arch/amd64/compile/ws amd64
Architecture: x86_64
Machine: amd64
>Description:
        cups doesn't print any longer with a current kernel.
>How-To-Repeat:
        Install cups from pkgsrc and try to print some file.
        Nothing will show up on the printer.
        If logging is enabled in /etc/syslog.conf (lpr.info),
        you'll notice a message like

        PID ... (/usr/pkg/libexec/cups/filter/pstops) stopped with status 1!

        It turns out to be a problem with kqueue used in cupsd.

        The problem can be reproduced with the following test program:

        #include <stdio.h>
        #include <errno.h>
        #include <fcntl.h>
        #include <stdlib.h>
        #include <string.h>
        #include <unistd.h>

        #include <sys/event.h>
        #include <sys/time.h>

        int
        main(int argc, char **argv)
        {
            int k, ret;
            char *err;

            printf("kqueue -> %d\n", k = kqueue());
            open("/dev/null", 0);
            switch (fork()) {
            case 0:
                ret = close(k);
                err = strerror(errno);
                printf("close -> %d", ret);
                printf(" (%s)\n", err);
                printf("dup-> %d\n", open("/dev/null", 0));
                exit(0);
            default:
                wait(NULL);
                return 0;
            }
        }

        The program will produce the followint output:

        kqueue -> 3
        close -> -1 (Bad file descriptor)
        dup-> 5

        As you can see, while the kqueue file descriptor is closed on
        the fork as documented, the subsequent dup doesn't pick up
        its file descriptor.  With cups this results in the filter
        not being started as expected, as it gets no stdin.
Fix:
        The problem is that the fd_freefile optimization, which tracks
        the lowest available file descriptor, isn't correctly maintained
        when the kqueue descriptor isn't copied from the parent to the
        child.

        The following diff fixes this:

        ===================================================================
        RCS file: /cvsroot/src/sys/kern/kern_descrip.c,v
        retrieving revision 1.197
        diff -u -r1.197 kern_descrip.c
        --- kern_descrip.c      8 Jun 2009 00:19:56 -0000       1.197
        +++ kern_descrip.c      30 Jun 2009 10:40:53 -0000
        @@ -1423,6 +1423,8 @@
                        }
                        if (__predict_false(fp->f_type == DTYPE_KQUEUE)) {
                                /* kqueue descriptors cannot be copied. */
        +                       if (i < newfdp->fd_freefile)
        +                               newfdp->fd_freefile = i;
                                continue;
                        }
                        /* It's active: add a reference to the file. */

>Fix:

Unknown
>Unformatted:
        
        


Home | Main Index | Thread Index | Old Index