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

VM freezes when user enters text in spawned process text field

    Details

    • Subcomponent:
    • CPU:
      x86
    • OS:
      windows_xp

      Description

      FULL PRODUCT VERSION :
      1.5.0_06
      Java SE 6.0 build 101

      ADDITIONAL OS VERSION INFORMATION :
      Windows XP 5.1.2600

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      This problem only occurs on machines configured with dual language support, e.g.:
      Japanese + US-English
      OR
      Chinese + US-English

      A DESCRIPTION OF THE PROBLEM :
      1) Java Process A instantiates Java Process B using Runtime.exec()

      2) Java Process B then launches a non-modal JDialog containing a JTextField, a JPasswordField, a JComboBox and 2 JButtons.

      3) Java Process B then starts a thread that monitors System.in for command-line input using a BufferedReader.

      4) The user is able to move the window around the screen, change combo-box selections with the mouse, click on the OK or Cancel buttons BUT if the user attempts to enter any text into either of the text fields, the application hangs until the parent process (Process A) is killed.

      If the user kills Java Process A (e.g. using ProcessExplorer from www.sysinternals.com) then Java Process B resumes normal execution.

      If the source code for Java Process B is modified so that it no-longer monitors System.in for input, the problem does not occur.

      This problem only occurs on Windows XP machines configured with multiple language support.

      I have tested this with jdk-6-rc-bin-b101-windows-i586-05_oct_2006.exe and
      the problem still exists.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1) Configure a Windows XP machine with multiple language support (e.g. US-English + Japanese) using the Regional settings control panel applet.

      2) Compile the following source code using JDK 1.5.0_06.

      3) Launch the application using the command: java -classpath . Launcher

      4) Wait for the dialog to appear on the screen.

      5) Attempt to enter some text in either of the text fields in the dialog.

      6) Notice that the application hangs and does not display the text that you attempted to type into the text fields.

      7) Kill the Launcher process & notice that immediately before the login dialog disappears, it is 'unblocked' and the text you entered appears momentarily before the dialog is closed.



      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I was expecting that typing text into the textfields would show the characters in the textfield and not hang the application.
      ACTUAL -
      The text does not appear in the textfield and the child process hangs until the parent process is killed. If System.in is not monitored for command-line input (e.g. by removing the code that configures the BufferedReader), then this problem does not occur.

      If the child process is launched directly from the command line, the problem does not occur. The problem appears to be specifically caused by the child process monitoring its InputStream System.in when the child process was created by another Java process using Runtime.exec(). Also, this problem does not occur on windows machines that are configured with a single US-English locale.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      No errors are displayed. The VM is simply hung until the parent process is killed.
      Note that the parent process is not hung, only the child process.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      /**
       * Monitor the command line for the 'exit' command
       */
      import java.io.BufferedReader;
      import java.io.InputStreamReader;
      public class InputCmdHandler extends Thread {
      public InputCmdHandler() {
      super("InputCommandHandler");
      }

         public void run () {
            try {
               BufferedReader br = new BufferedReader(
      new InputStreamReader(System.in));
               String s;
               while (!(s = br.readLine()).equals("exit")) {
                  Thread.sleep (5000);
               }
               System.exit (0);
            } catch (Exception ex) {
            }
         }
      }

      /**
       * This is the parent Process that launches the child process using
       * Runtime.exec()
       */
      import java.io.File;
      public class Launcher {
          private static final String COMMAND =
               "java -Djava.class.path=. LaunchTarget";

          String startingDir = "./";

          public static void main(String[] args) {
              new Launcher().launch();
          }
          
          public void launch() {
              try {
              
                  String cmd = COMMAND;
                  System.out.println("Executing command "+cmd);
                  
                  // start the new process
                  Process p = Runtime.getRuntime().exec(cmd,
                          null,
                          new File(startingDir));

                  // wait for the process to terminate
           boolean running = true;
           while (running) {
           try {
           Thread.sleep(1000);
           int exitValue = p.exitValue();
           running = false;
           } catch (InterruptedException ie) {
           ie.printStackTrace();
           } catch (IllegalThreadStateException ex) {
           System.out.println("Process is alive");
           }
           }
           System.out.println("Process terminated.");
                  
              } catch (Exception ex) {
                  ex.printStackTrace();
              }
          }
      }

      /**
       * A simple class that serves as a child process for the test application.
       * This class launches a non-modal dialog and then starts a thread to consume
       * input received on System.in.
       */
      import javax.swing.JFrame;
      public class LaunchTarget extends JFrame {
          public LaunchTarget() {
          }
          public void start() {
              LoginDialog dialog = new LoginDialog(this);
              dialog.setVisible(true);
          }
          public static void main (String[] args) {
              new LaunchTarget().start();
              new InputCmdHandler().start();
          }
      }

      /**
       * A simple non-modal dialog containing a JTextField, JPasswordField and two JButtons.
       * If either of the buttons is clicked, the application is terminated.
       */
      import java.awt.BorderLayout;
      import java.awt.FlowLayout;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import javax.swing.BorderFactory;
      import javax.swing.BoxLayout;
      import javax.swing.JButton;
      import javax.swing.JDialog;
      import javax.swing.JFrame;
      import javax.swing.JLabel;
      import javax.swing.JPanel;
      import javax.swing.JPasswordField;
      import javax.swing.JTextField;
      public class LoginDialog extends JDialog implements ActionListener {
          private JTextField name;
          private JPasswordField pwd;
          public LoginDialog(JFrame parent) {
              super(parent, "Login", false);
              name = new JTextField(16);
              pwd = new JPasswordField(16);
              JPanel main = new JPanel();
              main.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
              main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS));
              
              JPanel nameRow = new JPanel(new BorderLayout(5,5));
              nameRow.add(new JLabel("Name:"), BorderLayout.WEST);
              nameRow.add(name, BorderLayout.CENTER);
              main.add(nameRow);
              
              JPanel pwdRow = new JPanel(new BorderLayout(5,5));
              pwdRow.add(new JLabel("Password:"), BorderLayout.WEST);
              pwdRow.add(pwd, BorderLayout.CENTER);
              main.add(pwdRow);
              
              JPanel buttonRow = new JPanel(new FlowLayout(FlowLayout.LEFT,5,5));
              JButton ok = new JButton("OK");
              JButton cancel = new JButton("Cancel");
              ok.addActionListener(this);
              cancel.addActionListener(this);
              buttonRow.add(ok);
              buttonRow.add(cancel);
              main.add(buttonRow);
              
              getContentPane().add(main, BorderLayout.NORTH);
              pack();
              setLocationRelativeTo(null);
          }
          public void actionPerformed(ActionEvent evt) {
              System.exit(0);
          }
      }


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

      CUSTOMER SUBMITTED WORKAROUND :
      Remove the line of code from LaunchTarget that instantiates the InputCmdHandler.

        Attachments

          Activity

            People

            • Assignee:
              art Artem Ananiev
              Reporter:
              ndcosta Nelson Dcosta
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Imported:
                Indexed: