JavaFX does not recover after graphic card driver crash

Thorsten Fischer Thorsten_Fischer at gmx.de
Fri Jul 21 08:47:25 UTC 2023


Hi all,

first off all I want to say ‚thank you‘ to everyone in this community for all the effort you put in. I'm using JavaFX for years now and I'm really happy to work with it :)

I have the following issue/question: One of my customers experiences an application crash when running their JavaFX application for a longer period on a notebook with integrated Intel graphics. First of all, I think JavaFX does not cause the issue, but is rather affected by it. We built a workaround in JavaFX, but I'd like to discuss what a good solution would look like, so that it can be integrated into the JFX code base.

So, randomly between a couple of days to about 3 weeks the graphic card driver crashes. In the Windows (10) event log you can read: "Display driver igfx stopped responding and has successfully recovered.". In the console of the app it says: "D3DContext::testLostStateAndReset : Unknown D3D error 0x88760874". The app then just shows a black screen and keeps printing this error over and over to the console (rendering is triggered regularly in this app) and never recovers, even though the driver has been recovered and the whole system is running and is usable (again).

The error code 0x88760874 translates to D3DERR_DEVICEHUNG (https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3derr), what corresponds to the error in the Windows event log.

Now our initial workaround (within D3DContext.java#testLostStateAndReset) is basically the same as for D3DERR_DEVICEREMOVED, but with a loop to give the OS time to recover:

	public static final int D3DERR_DEVICEHUNG    	= 0X88760874;
	
	and at the end:
	
			if (hr == D3DERR_DEVICEHUNG) {
			setLost();

			long retryMillis = TimeUnit.MINUTES.toMillis(5);
			long sleepingMillis = TimeUnit.SECONDS.toMillis(1);

			for (int i = 0; i < retryMillis; i += sleepingMillis) {
				int cooperativeLevel = D3DResourceFactory.nTestCooperativeLevel(pContext);
				System.err.println("Checking Cooperative Level: " + cooperativeLevel);

				if (cooperativeLevel == D3D_OK) {
					break;
				} else {
					try {
						Thread.sleep(sleepingMillis);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}

			// reinitialize after 5 mins anyway, even if result is not OK.

			// Reinitialize the D3DPipeline. This will dispose and recreate
			// the resource factory and context for each adapter.
			D3DPipeline.getInstance().reinitialize();
		}

Yesterday we experienced with this workaround, that the app did actually recover after 20 seconds. The System.err output generated inside the loop only showed again the D3DERR_DEVICEHUNG error code, and after 20 sec. console showed the initialization output.

Very obviously Thread.sleep is not a good solution. To avoid it I thought about introducing another flag like isLost (-> "isHung") and

		if (hr == D3DERR_DEVICEHUNG) {
			setLost();
			setHung();
		}
		
		if (isHung && hr == D3D_OK) {
			isLost = false; // ?
			isHung = false;
			
            // Reinitialize the D3DPipeline. This will dispose and recreate
            // the resource factory and context for each adapter.
            D3DPipeline.getInstance().reinitialize();
		}
		
		
But before I continue with this direction (and because it takes weeks to reproduce this): Can anybody confidently tell me what a better/good solution may look like?

Thank you,
Thorsten
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20230721/a04c970e/attachment-0001.htm>


More information about the openjfx-dev mailing list