gtk_enumerate_printers may not call the destroy notification callback
@rluzynski
Submitted by Rafał Lużyński Link to original bug (#668863)
Description
Created attachment 206288 Test program: runs fine if CUPS is started, always hangs if CUPS is stopped
As the gtk_enumerate_printers() documentation says, the destroy argument is a function called when data is no longer needed. However, if
- CUPS is supported by GTK,
- and it is listed as the last on the list of the printing backends,
- and CUPS is not installed, not running, or not configured properly,
then the destroy notification callback is never called.
This happens because gtk_enumerate_printers() calls list_printers_init() and if list_printers_init() fails then it just returns. list_printers_init() may fail if the print backend reports status GTK_PRINT_BACKEND_STATUS_UNAVAILABLE. If this happens, list_printers_init() removes the backend from the printer_list->backends list. If this backend is the only item in this list then printer_list->backends becomes NULL. In all other places if printer_list->backends becomes NULL (or is never initialized) then free_printer_list(printer_list) is called which calls the destroy notification callback. However, in this case this callback is not called and the function just quits.
As a consequence:
- if the callback is used to free the allocated memory then a memory leak occurs,
- if the callback is used to notify the caller that all printers have been enumerated and the caller waits for the callback then caller hangs.
I attach a simple test program which runs fine if CUPS is running but always hangs if CUPS is turned off. Here is a copy of the test session:
========================================================================= $ ./printer_hangs This program hangs if CUPS subsystem is not running correctly Enumerating your printers: Printer name: Print to File destroy_notify called destroy_notify already called, end of the program $ su Password:
/etc/init.d/cups stop
Stopping cups: [ OK ]
exit
$ ./printer_hangs This program hangs if CUPS subsystem is not running correctly Enumerating your printers: Printer name: Print to File destroy_notify not yet called, waiting ^C $ su Password:
/etc/init.d/cups start
Starting cups: [ OK ]
exit
$ ./printer_hangs This program hangs if CUPS subsystem is not running correctly Enumerating your printers: Printer name: Print to File destroy_notify called destroy_notify already called, end of the program $
I have tested this on 3 different machines and the result is always the same. I have also checked the latest sources and they are same as 2.x series so I believe the behavior in 3.x series is the same.
You can compile the test program with:
gcc -o printer_hangs pkg-config --cflags --libs gtk+-2.0 gtk+-unix-print-2.0
printer_hangs.c
Attachment 206288, "Test program: runs fine if CUPS is started, always hangs if CUPS is stopped":
printer_hangs.c