简体   繁体   中英

JVM crashes when trying to claim a claimed printer JavaPOS EPSON Thermal Printer

I am using Epson_JavaPOS_ADK_11414_for_Linux_x64 for installing the JavaPOS with pcs ( sh installJavaPOSFull-64.sh )

I ran this program one after the other in different shells and the second process crashes for some reason:

import jpos.JposException;
import jpos.POSPrinter;
import jpos.util.JposPropertiesConst;

import java.time.Duration;
import java.time.Instant;

public class POSPrinterClaimTest {
  static POSPrinter posPrinter;

  private static Boolean isOpen = false;
  private static Boolean isClaimed = false;
  private static Boolean isEnabled = false;



  static {
    System.setProperty(
        JposPropertiesConst.JPOS_POPULATOR_FILE_PROP_NAME, "jpos.xml");
  }

  public static void main(String[] args) {
    try {
      posPrinter = new POSPrinter();
      Instant start = Instant.now();
      Instant finish = null;
      Long timeElapsed = null;
      openConnection("POSPrinter1");
      finish = Instant.now();
      timeElapsed = Duration.between(start, finish).toMillis();
      System.out.println("Time taken to connect : " + timeElapsed.toString());
      Thread.sleep(100000L);
      terminate();
      System.out.println("terminated from try block");
    } catch (JposException | InterruptedException e) {
      e.printStackTrace();
      try {
        terminate();
        System.out.println("terminated from catch block");
        Thread.sleep(5000);
      } catch (JposException | InterruptedException jposException) {
        jposException.printStackTrace();
      }
    } catch(Throwable t){
      t.printStackTrace();
    } finally {
      posPrinter = null;
    }
  }

  private static void openConnection(String printerName) throws JposException {
    try {

      String printerNamesss = printerName;
      /**
       * open the printer object according to the device logical name defined in jpos.xml
       */
      posPrinter.open(printerName);
      isOpen = true;
      System.out.println("opened");
      /**
       * Get the exclusive control right for the opened device.
       * Then the device is disable from other application.
       * */
      posPrinter.claim(3000);
      isClaimed = true;
      System.out.println("claimed");
      /**
       *  enable the device for input and output
       */
      posPrinter.setDeviceEnabled(true);
      isEnabled = true;
      System.out.println("enabled");

    } catch (JposException jposException) {
      System.out.println("jpos exception in open : " + jposException.getMessage());
      throw jposException;
    } catch(Throwable t) {
      System.out.println("unknown throwable open: " + t.getMessage());
    }
  }


  public static void terminate() throws JposException {
    try {
        if(isOpen && isClaimed) {
          posPrinter.clearOutput();
          System.out.println("cleared output");
        }

        if(isEnabled) {
          posPrinter.setDeviceEnabled(false);
          isEnabled = false;
          System.out.println("setDeviceEnabled false");
        }

        if(isClaimed) {
          posPrinter.release();
          isClaimed = false;
          System.out.println("released");
        }

        if(isOpen) {
          posPrinter.close();
          isOpen = false;
          System.out.println("closed");
        }
    } catch (JposException jposException) {
      jposException.printStackTrace();
      throw jposException;
    } catch(Throwable t) {
      System.out.println("unknown throwable terminate: " + t.getMessage());
    }
  }
}


First process output

opened
claimed
enabled
Time taken to connect : 7928 --> now I start the second process.
cleared output
setDeviceEnabled false
released
closed
terminated from try block

Second process output

opened
jpos exception in open : The port is already open.
jpos.JposException: The port is already open.
    at jp.co.epson.upos.core.v1_14_0001.pntr.CommonUPOSExceptionCreator.createJposException(CommonUPOSExceptionCreator.java:138)
    at jp.co.epson.upos.core.v1_14_0001.pntr.CommonUPOSExceptionCreator.createJposException(CommonUPOSExceptionCreator.java:99)
    at jp.co.epson.upos.core.v1_14_0001.pntr.CommonPrinterService.openPort(CommonPrinterService.java:3341)
    at jp.co.epson.upos.core.v1_14_0001.pntr.CommonPrinterService.claim(CommonPrinterService.java:3103)
    at jpos.BaseJposControl.claim(Unknown Source)
    at POSPrinterClaimTestThreads.openConnection(POSPrinterClaimTestThreads.java:73)
    at POSPrinterClaimTestThreads.test(POSPrinterClaimTestThreads.java:36)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
closed
terminated from catch block
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f43880ea9df, pid=12119, tid=0x00007f43690b0700
#
# JRE version: OpenJDK Runtime Environment (8.0_252-b09) (build 1.8.0_252-b09)
# Java VM: OpenJDK 64-Bit Server VM (25.252-b09 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [libethernetio31.so+0x1f9df]  CCommonPort::PortEvent(unsigned int, unsigned int, unsigned int*, unsigned int, unsigned char*)+0xf
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /POSPrinterTest/JavaPOS/hs_err_pid12119.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#
Aborted

If you see the second process throws a JposException which then initiates its catch and closes the connection. Then it suddenly crashes instead of sleeping for 5sec.

Any help?

After discussing this problem with EPSON team, they were able to provide a fix for the same with a new libepsonjpos.so and epsonjpos.jar

It solved two problems for me:

  1. The original claim issue in the post - resolved after using the latest libepsonjpos.so
  2. Multi-threaded printing in a single process in non-install mode (No-SetupPOS-insall)
    • the Epson team said to synchronize the POSPrinter.open() in all the threads and update the epsonjpos.jar with their fix

Some quotes on the issue from Epson Team.

Multi-thread issue - "Change History The fix that has been applied is in the device sharing logic. Only affects lite-mode (No-SetupPOS version) The different objects falsely assumed as equal. As result only the first connected printer has been used. The fix corrects that comparison logic."

Claim Issue - "We are glad we could help you. As for the background of the issues. The multi-process usage with non-install mode was a corner case for our JavaPOS ADK. With your help we could improve our testing cases."

Epson team said that they will release the patches in the next version.

It seems that the exclusive control processing of JavaPOS Service Object does not work well.

You should get a timeout error instead of an error that the port is already open.

However, your program is also bad.
The range of one try, catch is too wide.

JposException takes the form of an exception, but it's really just an error code notification.
Just because a JposException was signaled does not mean it crashes.
Most of the time, it will work if you eliminate the cause of the error and try again.

To be correct, try and catch each method call and property access.

The Epson_JavaPOS_ADK sample program should have been made that way.
Please code the same as the sample program.


In Addition:

Is what you see different?
It does try and catch in small units for each method and property, and does not propagate it to the top with throw.
Some of the sources I have are:

from "Epson_JavaPOS_ADK_11414_for_Linux_x64\\Sample\\Samples\\Printer\\PrinterSample_Step15\\src\\printersample_step15\\Step15Frame.java"

 // JavaPOS's code for Step7 // Set OutputCompleteEvent listener ptr.addOutputCompleteListener(this); // JavaPOS's code for Step7--END // JavaPOS's code for Step10 try { //Open the device. //Use the name of the device that connected with your computer. ptr.open("POSPrinter"); } catch(JposException ex){ JOptionPane.showMessageDialog(this, "This device has not been registered, or cannot use.", "",JOptionPane.WARNING_MESSAGE); //Nothing can be used. changeButtonStatus(); return; } try { //Get the exclusive control right for the opened device. //Then the device is disable from other application. ptr.claim(1000); bCoverSensor = ptr.getCapCoverSensor(); } catch(JposException ex){ JOptionPane.showMessageDialog(this, "Fails to get the exclusive access for the device.", "",JOptionPane.WARNING_MESSAGE); //Nothing can be used. changeButtonStatus(); return; }

Extracting the situation from the comment and posting:

Well, the error reported by Claim may be wrong, so why not contact EPSON support with detailed information about such a situation?

From OP:

Done that already but we don't know if they will respond back. So trying to find answer here; somewhere. :D

From OP:

I ran the same program in a single process with multiple threads in two pulses. I do now get the timeout error as you said. Only in different processes scenario, I am getting a crash

If so, there may be a problem with the interprocess exclusive control of the JavaPOS service object. That's the problem with it, but the crash could be a cleanup issue at the end of the exception, as I commented earlier. When an exception occurs in the Claim method, instead of ending the process by propagating the exception, call the Close method and try other cleanup to end normally.

From OP:

I wrote the posPrinter.close() in claim catch block. It worked and crash frequency reduced significantly when doing with two processes single threads. Still the crash happened once or twice. But in two processes each with 10 threads trying to claim printer results in one process able to claim and the other process crashing. try{ posPrinter.claim(3000); } catch(JposException ex) { posPrinter.close();}

It seems that the problem of exclusive control of JavaPOS service object of EPSON may remain. Please make additional inquiries to EPSON based on such survey information.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM