JDK-6604109 : javax.print.PrintServiceLookup.lookupPrintServices fails SOMETIMES for Cups
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 6
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2007-09-13
  • Updated: 2015-11-23
  • Resolved: 2011-10-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 JDK 8
6u111Fixed 7u95Fixed 8 b12Fixed
Description
FULL PRODUCT VERSION :
java version "1.6.0_02"
Java(TM) SE Runtime Environment (build 1.6.0_02-b05)
Java HotSpot(TM) Client VM (build 1.6.0_02-b05, mixed mode, sharing)

(from Debian)

also

java version "1.6.0_02-ea"
Java(TM) SE Runtime Environment (build 1.6.0_02-ea-b02)
Java HotSpot(TM) Client VM (build 1.6.0_02-ea-b02, mixed mode)

(latest JRE from the Sun homepage)

ADDITIONAL OS VERSION INFORMATION :
Linux 2.6.22-1-686 #1 SMP Sun Jul 29 14:37:42 UTC 2007 i686 GNU/Linux

EXTRA RELEVANT SYSTEM CONFIGURATION :
Cups 1.3.0

A DESCRIPTION OF THE PROBLEM :
Consider the following example program:

public static void main(String[] args)
{
  final PrintService[] services =
    PrintServiceLookup.
      lookupPrintServices(DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);

  System.err.println("found " + services.length);
}

If run repeatedly, this program will output "found 0" or "found 2", where 2 is the actual number of CUPS printers installed (both raw printers to a file).

The run that outputs "found 0" is thus wrong.

It seems that each time the correct output is produced, the method sun.print.UnixPrintServiceLookup.refreshServices() has been invoked from the thread PrinterChangeListener (defined in the same class), while each time the wrong output is produced, refreshServices() has been invoked from the calling thread through getPrintServices().

Further analysis shows that after refreshServices() has been invoked from the calling thread, the program throws a NullPointerException in PrintServiceLookup:367 in method getServices. It seems that services[1] is null even though getPrintServices() returned an array which had a non-null element 1.

This leads to the conclusion that the array must have been modified in the meantime, which may be possible if the aforementioned PrinterChangeListener has been invoked and modified this array.

If this was indeed a classic concurrency problem where PrinterChangeListener modifies the array that is used somewhere else, then setting the System Property "sun.java2d.print.polling" to "false" should prove as a viable workaround, which is indeed the case. The program invoked with -Dsun.java2d.print.polling=false seems to always output "found 2" after a few hundred runs.

Further inspection of UnixPrintServiceLookup reveals that refreshServices indeed modifies the members of the array variable printServices directly, which has been returned and is used by the caller as the abovementioned services from getPrintServices(). It thus seems plausible that the problem occurs because of these concurrency issues, which would also explain why it only occurs sometimes.

In any case, care must be taken to not modify any element of printServices at all, but to reset the member variable to a new array, as it is returned from getPrintServices(). This is, honestly, a pretty stupid bug which should not happen if a programmer knows anything about concurrency, which should be the case if this same programmer uses threads for the polling.


REPRODUCIBILITY :
This bug can be reproduced occasionally.

CUSTOMER SUBMITTED WORKAROUND :
invoke

System.setProperty("sun.java2d.print.polling", "false");

as first line of your program.

Comments
2D_Printing/Automated/PrintServiceLookup_2D
04-07-2013

EVALUATION Fixed as described - returned a clone of the array that is also used by the polling method.
24-10-2011