Skip site navigation (1)Skip section navigation (2)
Date:      30 Nov 2007 22:35:31 +0100
From:      "Arno J. Klaassen" <arno@heho.snv.jussieu.fr>
To:        Daniel Eischen <deischen@freebsd.org>
Cc:        nate@yogotech.com, java@freebsd.org
Subject:   Re: cvs commit: src/lib/libkse/thread thr_kern.c
Message-ID:  <wpprxrto0s.fsf@heho.snv.jussieu.fr>
In-Reply-To: <200711301716.lAUHGEV1064334@repoman.freebsd.org>
References:  <200711301716.lAUHGEV1064334@repoman.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
--=-=-=


Hello,

Daniel Eischen <deischen@freebsd.org> writes:

> deischen    2007-11-30 17:16:14 UTC
> 
>   FreeBSD src repository
> 
>   Modified files:
>     lib/libkse/thread    thr_kern.c 
>   Log:
>   Initialize the current thread and signal locks so that sigaction()
>   will work after a fork().


I spotted this patch wrt my .exec() problems.

Quick recall : I get strange exceptions in java-code doing quite
a lot of .exec() calls, but only on 2x2way SMP, not on UP or
single CPU SMP.

I get these problems under releng_6 as well, but 'my' only
2x2way SMP box is a production server I cannot test on.

Seeing this patch, I retested on a 2x2 SMP box running releng_7(amd64)
libmapping libthr.so.3 to libkse.so.3 for /usr/local/jdk1.5.0/bin/java_g.

I use the attached test-program (adapted after gentile remarks of Nate
Williams; I hope there's not yet another program error in it but it
does run flawlessly with libthr).

Running it like "/usr/local/jdk1.5.0/bin/java_g Test_cmd /tmp 0 "
it will produce a java_g.core after a number of iterations
with exit status 139.

Both with and without the above patch applied (to releng_7) the
gdb trace shows (I recompiled libkse with -g as well, but no
line-numbers showing up ) :

 gdb -core java_g.core /usr/local/jdk1.5.0/bin/java_g 
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "amd64-marcel-freebsd"...
Core was generated by `java_g'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libz.so.4...done.
Loaded symbols for /lib/libz.so.4
Reading symbols from /usr/lib/libkse.so.3...done.
Loaded symbols for /usr/lib/libkse.so.3
Reading symbols from /lib/libc.so.7...done.
Loaded symbols for /lib/libc.so.7
Reading symbols from /usr/local/jdk1.5.0/jre/lib/amd64/server/libjvm_g.so...done.
Loaded symbols for /usr/local/jdk1.5.0/jre/lib/amd64/server/libjvm_g.so
Reading symbols from /usr/lib/libstdc++.so.6...done.
Loaded symbols for /usr/lib/libstdc++.so.6
Reading symbols from /lib/libm.so.5...done.
Loaded symbols for /lib/libm.so.5
Reading symbols from /lib/libgcc_s.so.1...done.
Loaded symbols for /lib/libgcc_s.so.1
Reading symbols from /usr/local/jdk1.5.0/jre/lib/amd64/native_threads/libhpi_g.so...done.
Loaded symbols for /usr/local/jdk1.5.0/jre/lib/amd64/native_threads/libhpi_g.so
Reading symbols from /usr/local/jdk1.5.0/jre/lib/amd64/libverify_g.so...done.
Loaded symbols for /usr/local/jdk1.5.0/jre/lib/amd64/libverify_g.so
Reading symbols from /usr/local/jdk1.5.0/jre/lib/amd64/libjava_g.so...done.
Loaded symbols for /usr/local/jdk1.5.0/jre/lib/amd64/libjava_g.so
Reading symbols from /usr/local/jdk1.5.0/jre/lib/amd64/libzip_g.so...done.
Loaded symbols for /usr/local/jdk1.5.0/jre/lib/amd64/libzip_g.so
Reading symbols from /libexec/ld-elf.so.1...done.
Loaded symbols for /libexec/ld-elf.so.1
#0  0x000000080075d151 in pthread_sigmask () from /usr/lib/libkse.so.3
[New Thread 0x800b20800 (runnable)]
[New Thread 0x800b1e800 (sleeping)]
[New Thread 0x800b1e000 (sleeping)]
[New Thread 0x800b1dc00 (runnable)]
[New Thread 0x800b1d800 (sleeping)]
[New Thread 0x800b1d400 (sleeping)]
[New Thread 0x800b1d000 (sleeping)]
[New Thread 0x800b1cc00 (sleeping)]
[New Thread 0x800b1c800 (sleeping)]
[New Thread 0x800b1c000 (sleeping)]
[New Thread 0x800b1bc00 (LWP 100313)]
[New Thread 0x800b19400 (sleeping)]
[New LWP 100288]
(gdb) where
#0  0x000000080075d151 in pthread_sigmask () from /usr/lib/libkse.so.3
#1  0x000000080075d103 in sigprocmask () from /usr/lib/libkse.so.3
#2  0x000000080076c423 in pthread_kill () from /usr/lib/libkse.so.3
#3  0x0000000800758f29 in fork () from /usr/lib/libkse.so.3
#4  0x0000000801e43158 in jdk_fork_wrapper ()
    at ../../../src/solaris/native/java/lang/UNIXProcess_md.c:437
#5  0x0000000801e43570 in Java_java_lang_UNIXProcess_forkAndExec (
    env=0x812a6f198, process=0x7ffffedf1608, prog=0x7ffffedf1600, 
    argBlock=0x7ffffedf15f8, argc=2, envBlock=0x0, envc=0, path=0x0, 
    redirectErrorStream=0 '\0', stdin_fd=0x7ffffedf15c8, 
    stdout_fd=0x7ffffedf15c0, stderr_fd=0x7ffffedf15b8)
    at ../../../src/solaris/native/java/lang/UNIXProcess_md.c:595
#6  0x0000000805086be0 in ?? ()
#7  0x0000000800000000 in ?? ()
#8  0x0000000000000000 in ?? ()
#9  0x00007fff00000000 in ?? ()
#10 0x00007ffffedf15c8 in ?? ()
#11 0x00007ffffedf15c0 in ?? ()
#12 0x00007ffffedf15b8 in ?? ()
#13 0x00007ffffedf1550 in ?? ()
#14 0x00007ffffedf157c in ?? ()
#15 0x00007ffffedf1560 in ?? ()
#16 0x0000000800e4ae4d in ThreadLocalStorage::pd_raw_thread_id ()
    at threadLS_bsd_amd64.hpp:37


Kernel-config is stripped GENERIC with the following extras :

options CLK_USE_I8254_CALIBRATION

options COMPAT_LINUX32
options LINPROCFS
options LINSYSFS


options         SCHED_ULE
options IPI_PREEMPTION
options NO_ADAPTIVE_MUTEXES
options MUTEX_DEBUG


I hope this is of use, and if so, feel free to ask me for more info/tests.

Best,

Arno



--=-=-=
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=Test_cmd.java

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.StringTokenizer;

final class Test_cmd
{
  public static void main (String[] args) throws Exception
  {
    final String path = args[0];
    final long max_wait_time_ms = Long.parseLong(args[1]);
    final String[] cmd = new String[3];

    cmd[0] = "/bin/sh";
    cmd[1] = "-c";
    cmd[2] = "sync; if [ -e "  + path + " ]; then df -k " + path;
    cmd[2] += ";else echo; echo \"x -1 -1 0\";fi ";

    for (int i= 1; i <= 999; i++)
      {
        final StringBuffer parsed_std_out = new StringBuffer();
        int last_line_start_index = 0;
        final String line;
        final StringTokenizer st;
        final int nr_of_tokens;
        long free_bytes = -1;

        System.out.println("test <" + i + ">.");

        execute_command(cmd, max_wait_time_ms, parsed_std_out);

        last_line_start_index = parsed_std_out.lastIndexOf("\n") + 1;
        if (last_line_start_index < 0)
          {
            System.err.println("Failed to find last line start index!");
            continue;
          }

        line = parsed_std_out.substring(last_line_start_index,
            parsed_std_out.length());
        if (line == null)
          {
            System.err.println("Failed to find last line in std out!");
            continue;
          }

        st = new StringTokenizer(line);

        nr_of_tokens = st.countTokens();
        if (nr_of_tokens >= 4)
          {
            final String free_space_str;

            // Filesystem
            st.nextToken();

            // 1K-blocks
            st.nextToken();

            // Used
            st.nextToken();

            // Avail
            free_space_str = st.nextToken();

            try
              {
                free_bytes = Long.parseLong(free_space_str);
              }
            catch (NumberFormatException nfe)
              {
                free_bytes = -1;
                nfe.printStackTrace();
              }

            free_bytes *= 1024;
          }

        System.out.println("free bytes <" + free_bytes + ">.");
      }
  }

  /*
   * if _max_wait_time_ms != 0, wait _max_wait_time_ms for std out only 
   * to finish. So std err ain't checked, and neither is the process itselves!!
   * For the process we simply call detroy in the finally clause
   * else wait "for ever" untill process has finished.
   */
  public static boolean execute_command(final String[] _cmd, 
      final long _max_wait_time_ms, final StringBuffer _parsed_std_out)
  {
    boolean ok = false;
    String full_cmd = "";
    Process proc = null;
    int exit_value = 0;
    Stream_reader std_out = null;
    Stream_reader std_err = null;

    try
      {
        for (int i = 0; i < _cmd.length; i++)
          {
            if (i > 0)
              full_cmd += " ";

            full_cmd += _cmd[i];
          }

        proc = Runtime.getRuntime().exec(_cmd);
        std_out = new Stream_reader(proc.getInputStream());
        std_err = new Stream_reader(proc.getErrorStream());

        if (_max_wait_time_ms == 0)
          {
            proc.waitFor ();
            std_out.wait_for();
          }
        else
          std_out.join(_max_wait_time_ms);


        if (_parsed_std_out != null)
          _parsed_std_out.append(std_out.get_data());

        if ( (exit_value = proc.exitValue ()) != 0)
          {
            System.err.println("Command <" + full_cmd 
                + "> finished with exit value <" + exit_value + "> Std error is:\n"
                + std_err.get_data());
          }
        else
          ok = true;
      }
    catch (InterruptedException int_ex)
      {
        System.err.println("Command <" + full_cmd 
                + "> failed with interrupted exception!");
        int_ex.printStackTrace();
        exit_value = 1;
        ok = false;
      }
    catch (IOException io_ex)
      {
        System.err.println("Command <" + full_cmd 
                + "> failed with IO exception!");
        io_ex.printStackTrace();
        io_ex.printStackTrace();
        exit_value = 1;
        ok = false;
      }
    catch (Exception ex)
      {
        System.err.println("Command <" + full_cmd 
                + "> failed with exception!");
        ex.printStackTrace();
        exit_value = 1;
        ok = false;
      }
    finally
      {
        if (proc != null)
          proc.destroy ();

        if (std_out != null)
          std_out.stop();

        if (std_err != null)
          std_err.stop();
      }

    return ok;
  } /* execute_command */

  private static class Stream_reader implements Runnable
  {
    private final InputStream input_stream;
    private final StringBuffer data;
    private final Thread thread;

    private boolean stop = false;

    private static final String LINE_SEP = "\n";

    private Stream_reader(final InputStream _input_stream)
    {
      this.input_stream = _input_stream;

      data = new StringBuffer();

      thread = new Thread (this, "Stream_reader");
      thread.setPriority (Thread.NORM_PRIORITY);
      thread.start ();
    }

    public void run()
    {
      try
        {
          BufferedReader buffered_reader = new BufferedReader(
              new InputStreamReader(input_stream));

          while (stop == false)
            {
              final String line;

              line = buffered_reader.readLine();
              if (line == null)
                break;

              if (data.length() > 0)
                data.append(LINE_SEP);
              data.append(line);
            }

          buffered_reader.close();
        }
      catch (java.io.IOException io_ex)
        {
          /* do nothing */
        }
    } /* run */

    private String get_data()
    {
      return data.toString();
    } /* get_data */

    private void stop()
    {
      stop = true;
    } /* stop */

    private void wait_for()
    {
      join(0);
    } /* wait_for */

    private void join(final long _max_time_ms)
    {
      try
        {
          thread.join(_max_time_ms);
        }
      catch (InterruptedException int_ex)
        {
          int_ex.printStackTrace();
        }
    } /* join */
  } /* class Stream_reader */
}



--=-=-=--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?wpprxrto0s.fsf>