I am working on a small app that should sign documents using digital signature and quit. The signature can be in a PKCS#12 archive (.pfx file) or on a smartcard device.
Working with the pfx file is easy and working fine.
However, sometimes using the smartcard device, the process hangs on Windows 8 PCs.
The document is signed correctly, but the process doesn't terminate. It just hangs.
I'm using the Sun's PKCS#11 provider - sun.security.pkcs11.SunPKCS11
Basically I'm doing this:
SunPKCS11 provider = new SunPKCS11(configuration);
Security.addProvider(provider);
..... some work .....
provider.logout()
Security.removeProvider(provider);
Now... even if I call System.exit(0)
or throw an exception at the end of the main
method, I can see the stacktrace in the output but the process doesn't terminate.
I've added a shutdown hook to see if it is executed and it is, i.e. the JVM is trying to stop.
The hang occures rarely, only on Windows 8 PCs. Tried with different smartcards and it happens only with cards that use cmp11.dll
(dlls are provided from the vendors of the smartcards).
Using the same dll for communication with the smartcard, however, works fine on Windows 7, XP or some Windows 8 PCs
Running it with Java 8, Update 45, on either x86 or x64 Windows 8
Tried to get a thread dump to see what is hanging:
public static void main(String[] args) {
// do my job, register provider, sign documents, remove provider ...
for(int i = 0; i < 20; ++i) {
System.err.println("Sleep... " + i);
Thread.sleep(2 * 1000);
}
System.err.println("Exiting...");
}
If I execute jstack -l 3232 > dump.log 2>&1
when Sleep... x
is printing, everything looks OK.
However, if I execute jstack -F -l 3232 > dump2.log 2>&1
when Exiting...
is printed and the app hangs (using -F
because the process hangs), i got the following:
Attaching to process ID 3232, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.45-b02
Deadlock Detection:
No deadlocks found.
Thread Exception in thread "main"
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at sun.tools.jstack.JStack.runJStackTool(JStack.java:140)
at sun.tools.jstack.JStack.main(JStack.java:106)
Caused by: sun.jvm.hotspot.debugger.DebuggerException: Windbg Error: GetThreadIdBySystemId failed!
at sun.jvm.hotspot.debugger.windbg.WindbgDebuggerLocal.getThreadIdFromSysId0(Native Method)
at sun.jvm.hotspot.debugger.windbg.WindbgDebuggerLocal.getThreadIdFromSysId(WindbgDebuggerLocal.java:284)
at sun.jvm.hotspot.debugger.windbg.amd64.WindbgAMD64Thread.getThreadID(WindbgAMD64Thread.java:88)
at sun.jvm.hotspot.debugger.windbg.amd64.WindbgAMD64Thread.toString(WindbgAMD64Thread.java:81)
at java.lang.String.valueOf(String.java:2982)
at java.io.PrintStream.print(PrintStream.java:683)
at sun.jvm.hotspot.runtime.win32_amd64.Win32AMD64JavaThreadPDAccess.printThreadIDOn(Win32AMD64JavaThreadPDAccess.java:114)
at sun.jvm.hotspot.runtime.JavaThread.printThreadIDOn(JavaThread.java:265)
at sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:79)
at sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:45)
at sun.jvm.hotspot.tools.JStack.run(JStack.java:66)
at sun.jvm.hotspot.tools.Tool.startInternal(Tool.java:260)
at sun.jvm.hotspot.tools.Tool.start(Tool.java:223)
at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
at sun.jvm.hotspot.tools.JStack.main(JStack.java:92)
... 6 more
I can see the process with PID 3232 in the task manager!
Any idea why it is not terminating or why jstack
fails?
EDIT
Ok, tried to extract the signing in a separate process, execute it with Runtime.exec
and then kill it with Process.destroy
but... doesn't seem to help. The child process still stays in the task manager.
Aaaaand... now I have no other choice but to make it kill itself ;(
try {
String name = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
Runtime.getRuntime().exec("taskkill.exe /F /PID " + name.split("@")[0]);
}
catch(Throwable t) {
Runtime.getRuntime().exec("taskkill.exe /F /IM java.exe");
}
EDIT 2
Tried with Runtime.halt
as well. Still doesn't terminate the process...
I would appreciate any ideas!
This won't address your root cause, but this method can be used to force the JVM to terminate:
http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#halt(int)
As the Javadoc says, use with extreme caution ;-)
I have some problem with sun.security.pkcs11.SunPKCS11 on Windows 8 PCs.This is working for me:
Runtime.getRuntime().exec("taskkill.exe /F /PID " + name.split("@")[0]);
Thread.sleep(500);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With