Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8201570

Get two bytes for the Linux input event type, not four

XMLWordPrintable

    • x86
    • linux_ubuntu

      ADDITIONAL SYSTEM INFORMATION :
      The Java VM is Oracle JDK 8 Update 172 (an early-access build) with the OpenJFX 8 x86egl overlay bundle built from sources on April 10, 2018. The test system is a Dell Inspiron 1011 netbook with 1 GB of RAM and a 1.60 GHz Intel Atom N270 processor with hyper-threading enabled (2 logical processors). This is an 32-bit Intel system running Ubuntu 16.04.4 LTS as follows:

      $ uname -a
      Linux mini10v 4.13.0-38-generic #43~16.04.1-Ubuntu SMP Wed Mar 14 17:46:42 UTC 2018 i686 i686 i686 GNU/Linux

      $ ldd --version
      ldd (Ubuntu GLIBC 2.23-0ubuntu10) 2.23

      $ getconf GNU_LIBPTHREAD_VERSION
      NPTL 2.23

      $ ~/opt/jdk1.8.0_172/bin/java -version
      java version "1.8.0_172-ea"
      Java(TM) SE Runtime Environment (build 1.8.0_172-ea-b03)
      Java HotSpot(TM) Client VM (build 25.172-b03, mixed mode)


      A DESCRIPTION OF THE PROBLEM :
      The Linux input event type is defined in "linux/input.h" as an unsigned short, two bytes in size:

      ---------------------------------------------------------------------
      /*
       * The event structure itself
       */

      struct input_event {
              struct timeval time;
              __u16 type;
              __u16 code;
              __s32 value;
      };
      ---------------------------------------------------------------------

      Yet the first statement in the put(ByteBuffer) method of com.sun.glass.ui.monocle.LinuxEventBuffer reads four bytes for the event type by calling ByteBuffer.getInt(int) as follows:

      ---------------------------------------------------------------------
      boolean isSync = event.getInt(eventStruct.getTypeIndex()) == 0
              && event.getInt(eventStruct.getValueIndex()) == 0;
      ---------------------------------------------------------------------

      The other occurrences in LinuxEventBuffer use the correct ByteBuffer.getShort(int) method to get the event type.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run any JavaFX program with mouse or keyboard input.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      There are no external symptoms for the error.
      ACTUAL -
      There are no external symptoms for the error. In my tests, the processing of the event works despite the error because when the even type is zero, the event code is also zero, so getting both values by accident when checking just the first doesn't cause problems (see EV_SYN and SYN_REPORT in "linux/input-event-codes.h"). But synchronization events can contain non-zero event codes (SYN_CONFIG, SYN_MT_REPORT, SYN_DROPPED, SYN_MAX), so it may be better to fix the error in any case for these other possibilities.


      ---------- BEGIN SOURCE ----------
      You can use the simple JavaFX application below for testing:

      ---------------------------------------------------------------------
      package org.status6.hello;

      import javafx.application.Application;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.layout.StackPane;
      import javafx.stage.Stage;

      public class HelloApp extends Application {

          private static final String TITLE = "Hello App";
          private static final String LABEL = "Say Hello";
          private static final String MESSAGE = "Hello World!";
          private static final int WIDTH = 800;
          private static final int HEIGHT = 600;

          @Override
          public void start(Stage stage) {
              Button button = new Button();
              button.setText(LABEL);
              button.setOnAction(e -> System.out.println(MESSAGE));

              StackPane root = new StackPane();
              root.getChildren().add(button);
              Scene scene = new Scene(root, WIDTH, HEIGHT);

              stage.setTitle(TITLE);
              stage.setScene(scene);
              stage.show();
          }

          public static void main(String[] args) {
              launch(args);
          }
      }
      ---------------------------------------------------------------------

      Run the program with the system property "monocle.input.traceEvents.verbose=true", click the button, and you should see output similar to that shown below:

      ---------------------------------------------------------------------
      $ sudo ~/opt/jdk1.8.0_172/bin/java \
          -Dglass.platform=Monocle -Dmonocle.platform=Linux -Dprism.order=sw \
          -Dmonocle.input.traceEvents.verbose=true -jar ~/lib/hello.jar
      traceEvent: Set MouseState[x=400,y=300,wheel=0,buttonsPressed=IntSet[]]
      traceEvent: Read EV_MSC MSC_SCAN 589825 [index=0]
      traceEvent: Read EV_KEY BTN_MOUSE 1 [index=16]
      traceEvent: Read EV_SYN SYN_REPORT 0 [index=32]
      traceEvent: Processing EV_MSC MSC_SCAN 589825 [index=0]
      traceEvent: Processing EV_KEY BTN_MOUSE 1 [index=16]
      traceEvent: Processing EV_SYN SYN_REPORT 0 [index=32]
      traceEvent: Set MouseState[x=400,y=300,wheel=0,buttonsPressed=IntSet[212]]
      traceEvent: Compacted event buffer java.nio.HeapByteBuffer[pos=0 lim=16000 cap=16000]
      traceEvent: Read EV_MSC MSC_SCAN 589825 [index=0]
      traceEvent: Read EV_KEY BTN_MOUSE 0 [index=16]
      traceEvent: Read EV_SYN SYN_REPORT 0 [index=32]
      traceEvent: Processing EV_MSC MSC_SCAN 589825 [index=0]
      traceEvent: Processing EV_KEY BTN_MOUSE 0 [index=16]
      traceEvent: Processing EV_SYN SYN_REPORT 0 [index=32]
      traceEvent: Set MouseState[x=400,y=300,wheel=0,buttonsPressed=IntSet[]]
      traceEvent: Compacted event buffer java.nio.HeapByteBuffer[pos=0 lim=16000 cap=16000]
      Hello World!
      ^C
      ---------------------------------------------------------------------

      You must run the program as root so that the program has permission to access the Linux input and framebuffer devices. Notice that the event code EV_SYN (value 0) is always paired with SYN_REPORT (value 0), so the bug doesn't cause problems in this case.

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      A fix for the problem is found here:

      Get only two bytes for the Linux input event type
      https://gitlab.com/openjfxepd/jfxpatch/commit/0da2298f2e6e41e3c7bf5748c40ec459c6d810f1

      For completeness, I have also included the full patch below:

      ---------------------------------------------------------------------
      From 0da2298f2e6e41e3c7bf5748c40ec459c6d810f1 Mon Sep 17 00:00:00 2001
      From: John Neffenger <john@status6.com>
      Date: Thu, 3 Nov 2016 14:31:51 -0700
      Subject: [PATCH] Get only two bytes for the Linux input event type

      The Linux input event type is defined in <linux/input.h> as an unsigned
      short, two bytes in size, but the constructor for LinuxEventBuffer reads
      four bytes for the type by calling the method getInt(int). Change this
      method call to getShort(int).

      Fixes #3
      ---
       src/com/sun/glass/ui/monocle/LinuxEventBuffer.java | 2 +-
       1 file changed, 1 insertion(+), 1 deletion(-)

      diff --git a/src/com/sun/glass/ui/monocle/LinuxEventBuffer.java b/src/com/sun/glass/ui/monocle/LinuxEventBuffer.java
      index 6a2471a..a97124a 100644
      --- a/src/com/sun/glass/ui/monocle/LinuxEventBuffer.java
      +++ b/src/com/sun/glass/ui/monocle/LinuxEventBuffer.java
      @@ -90,7 +90,7 @@ class LinuxEventBuffer {
            */
           synchronized boolean put(ByteBuffer event) throws
                   InterruptedException {
      - boolean isSync = event.getInt(eventStruct.getTypeIndex()) == 0
      + boolean isSync = event.getShort(eventStruct.getTypeIndex()) == 0
                       && event.getInt(eventStruct.getValueIndex()) == 0;
               while (bb.limit() - bb.position() < event.limit()) {
                   // Block if bb is full. This should be the
      --
      libgit2 0.27.0
      ---------------------------------------------------------------------


      FREQUENCY : always


            jvos Johan Vos
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: