10 Replies Latest reply: Jun 6, 2012 6:21 PM by EJP RSS

    Stuck Inside Native Method

    638189
      I have developed some Java code to call a third party DLL using JNI. Most of the time everything works as expected, but once in a while (generally after several days of processing) my program hangs. The root cause appears to be related to an intermittent issue with the driver that I am calling, something that I have no control over. When I perform a thread dump I can see that the thread is "stuck" inside the native method that I am calling. I am able to detect the hangup using a timer, and even obtain the "stuck" thread, but I cannot kick it back into life...or kill it in any way. Does anyone have any ideas?

      My code that is calling the native method is as follows:
      public void process() {
          System.out.println("Hello world from Java");
          Timer timer = new Timer();
          timer.schedule(new MyTimerTask(), 1000);
          myNativeMethod();
          System.out.println("Goodbye world from Java");
      }
      And the code for my timer task is as follows:
      public class MyTimerTask extends TimerTask {
          @Override
          public void run() {
              System.out.println("Timeout");
              ThreadGroup tg = Thread.currentThread().getThreadGroup();
              Thread[] list = new Thread[tg.activeCount()];
              tg.enumerate(list);
              for (Thread t : list) {
                  System.out.println(t);
                  System.out.println("---------------------------------------");
                  StackTraceElement[] st = t.getStackTrace();
                  for (StackTraceElement ste : st) {
                      System.out.println(ste);
                      if (ste.getMethodName().equals("myNativeMethod") && ste.isNativeMethod()) {
                          System.out.println("stuck thread " + t.getName() + " detected!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                          t.interrupt();
                          break;
                      }
                  }
              }
          }
      }
        • 1. Re: Stuck Inside Native Method
          KevinPas
          What does the DLL do? Do you get data out of it? Can you launch it in a separate java Process?

          private Process process = null;

          // The following only works in Windows.
          // Something like this might work in Linux: String command="ps -A -U "+System.getProperty("user.name")+" -d";
          String line;

          Process p = Runtime.getRuntime().exec("tasklist.exe /FI \"IMAGENAME eq " + "name of process" + "\"");
          BufferedReader input = new BufferedReader (new InputStreamReader(p.getInputStream()));

          while ((line = input.readLine()) != null) {
          if ( line.contains( "name of process" ) ) {
          alreadyLoaded = true; // Already Loaded.
          break;
          }
          }

          // Try to load it.
          if ( alreadyLoaded == false )
          {
          process = Runtime.getRuntime().exec( path + " -m" );
          }

          else
          {
          }
          • 2. Re: Stuck Inside Native Method
            KevinPas
            I forgot. Then you can kill it.

            if ( process != null )
            process .destroy ();

            Edited by: KevinPas on Jun 5, 2012 4:36 PM
            • 3. Re: Stuck Inside Native Method
              638189
              Thanks for your response KevinPas.

              I am communicating with PC/SC smart card readers, using the javax.smartcardio classes, and it is these classes that are actually communicating with a DLL, so it's not really possible for me to use the approach that you have suggested. I really just wanted to illustrate a simplified view of what is happening with my code above. In an effort to simulate the issue in a repeatable manner I developed a DLL that simply contains an infinite loop, this is what I then called in my illustration.
              • 4. Re: Stuck Inside Native Method
                EJP
                There's no guarantee that interrupt() can interrupt everything. java.io comes to mind. You might have to use System.exit() ;-(
                • 5. Re: Stuck Inside Native Method
                  638189
                  You are quite correct EJP, interrupt() was doing nothing for me. Unfortunately using System.exit() is not an option in my solution, as the final code will be running inside the JBoss application server. I was really hoping for a solution that would not require a re-start of the application server, but it is looking more and more as if this is unlikely.
                  • 6. Re: Stuck Inside Native Method
                    EJP
                    As it's a server you must use a separate process as per the suggestion above, no two ways about it.
                    • 7. Re: Stuck Inside Native Method
                      638189
                      Just so I am clear, do you mean that:
                      a) As it's a server I must use a separate process to communicate with a DDL because that's the only way to communicate with a DLL inside the server
                      b) As it's a server I must use a separate process to communicate with a DLL if I want to be able to kill a stuck process

                      I am assuming that you mean b), which is not really an option due to the fact that it is not my code that is communicating with the DLL, it is the javax.smartcardio classes that are communicating with the DLL. I could of course not use the javax.smartcardio classes and write something myself, but I figured there wasn't much point in re-inventing the wheel if I didn't need to.
                      • 8. Re: Stuck Inside Native Method
                        KevinPas
                        Just to finish my thought which will only be useful as a last resort and only if you have permissions to do this on your server:

                        It seems possible, but maybe not practical and a lot of extra work:

                        1) Launch a separate process that runs your dll (or the code that uses the dll).
                        2) Pass a tcp port number on the command line when you start it.
                        3) Get and set values via tcp
                        4) If it locks up (you say you know when that happens) have the tcp client ask for a process kill.
                        5) Maybe your primary app can destroy the secondary process (which should dump the dll too) and restart it.

                        No need to respond I'm just doing a brain dump.

                        Edited by: KevinPas on Jun 6, 2012 9:26 AM

                        Edited by: KevinPas on Jun 6, 2012 9:31 AM
                        • 9. Re: Stuck Inside Native Method
                          jschellSomeoneStoleMyAlias
                          StuartyBoarder wrote:
                          a) As it's a server I must use a separate process to communicate with a DDL because that's the only way to communicate with a DLL inside the server
                          No
                          b) As it's a server I must use a separate process to communicate with a DLL if I want to be able to kill a stuck process
                          Absolutely.
                          I am assuming that you mean b), which is not really an option
                          A process is a process. Doesn't matter what it runs.

                          An advantage that hasn't been mentioned in terms of a separate process is that if the dll has a system exception it will cause the process to exit. And there is no way to stop that. If that process is your JBoss server then it will exit. Which probably isn't what you want.

                          As a separate process if if exits all you need to is detect that (via correct usage of Process) and then just start it up again.
                          • 10. Re: Stuck Inside Native Method
                            EJP
                            Just so I am clear, do you mean that:
                            a) As it's a server [snip]
                            None of the above. As it's a server that you don't want to restart you must put the bits that get stuck into a separate process that you can restart.