Comment 8 for bug 855445

Revision history for this message
Till Kamppeter (till-kamppeter) wrote :

I have investigated the problem more and found a simple workaround, but not a fix:

When creating or removing a queue, the printer is (un)registered for DNS-SD broadcasting this queue and CUPS (all in scheduler/dirsvc.c) keeps in an array (DNSSDPrinters) which queues are broadcasting. CUPS adds the DNS-SD service name to the printer's record (reg_name in cupsd_printer_s, scheduler/printers.h) and then adds the record to the array (scheduler/dirsvc.c, line 2903), with the service name as sorting/searching criteria (dnssdComparePrinters() function).

When it removes a queue, CUPS searches the record in the array to remove it and afterwards sets the service name in the record to NULL (scheduler/dirsvc.c, line 2680). When creating a queue CUPS searches the array to find the correct place for the new record, so that they keep sorted. All this is done by CUPS' own array infrastructure in cups/array.c.

On this array search (it does a binary search, function cups_array_find() in cups/array.c) it chokes on a record in the array where the pointer to the service name (p->reg_name) is neither the start address of a string nor 0 (NULL), but 1 (!), so it is a pointer to the memory address 0x1 (see variable t in step #0 of the back trace). I did not find out how this happened, but I can work around it by defining the array without comparison function (set it to NULL in line 1653 of scheduler/dirsvc.c), getting an unsorted array which is searched linearly with only pointer comparisons (cups/array.c, line 104):

    for (current = 0; current < a->num_elements; current ++)
      if (a->elements[current] == e)
      {
        diff = 0;
        break;
      }

Array size is the number of locally defined queues. Most users have less than 100. If it comes high a server has around 10000 queues. So searching linearly here should not introduce a too high delay and the workaround therefore should not be a problem.

Applying the workaround at least for Oneiric ...