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

JNDI wake up when clock_settime() is called

XMLWordPrintable

    • b01
    • sparc
    • solaris_10

        JNDI threads are not sleeping after another program calls clock_settime() (Like NTP for Solaris does).

        The test case is below, one C program mimics the behavior of NTP to use clock_settime() to change the time (just incase your NTP is up to date, so the clock doesn't actually change with NTP). The other program uses Java and JNDI. I guess this problem happens with both 5u13 and 6u7 jvms.

        Here's the code:
        The C program below uses this function below to emulate NTP behavior. So, you
        can also use NTP as the trigger as long as you can get it "step" the
        time.

        #include <sys/time.h>
        #include <stdio.h>
        #include <stdlib.h>

        int main(int argc, char *argv[])
        {
           struct timeval currTime;
           struct timespec tp;

           if (argc < 2){
               perror("Command: SetSysTime interval\n");
               return 1;
           }
           int interval = atoi(argv[1]);


           printf("Adjusting system time...\n");
           int ret = clock_gettime(CLOCK_REALTIME, &tp);
           if (ret == 0)
               printf("System time retrieved successfully: %d \n", tp.tv_sec);
           else
               printf("System time NOT retrieved successfully\n");

           tp.tv_sec += interval;
           ret = clock_settime(CLOCK_REALTIME, &tp);
           if (ret == 0)
               printf("System time was set successfully\n");
           else
               printf("System time was NOT set successfully\n");

           printf("System time was adjusted by %d sec\n", interval);
        }


        If you run the above program to adjust system clock, then you
        enter something as the input to the 2nd program below so that it
        continues. You can see the code executed right after your input will
        wake up other sleeping threads prematurely. You can run the 2nd program
        with a thread sleeping time longer (e.g. 180) to make the problem shown
        more obviously. The 2nd program below is a java program. You will need
        to update the line of looking up LDAP server with your own LDAP IP
        address before compiling.

        ------- Start File TestSleep.java -------

        import java.io.*;
        import javax.naming.*;
        import javax.naming.directory.*;


        public class TestSleep implements Runnable {

          Thread mThread = null;
          DirContext dirContext = null;

          public TestSleep(){
            try{
              InitialContext mInitCtx = new InitialContext();
              dirContext =
        (DirContext)mInitCtx.lookup("ldap://xxx.xxx.xxx.xxx:xxx/");
            } catch (Exception ex){
              ex.printStackTrace();
            }
              mThread = new Thread(this);
              mThread.start();
          }


          public void run(){
              System.out.println("New thread is running...");
              BufferedReader reader = new BufferedReader(new
        InputStreamReader(System.in));
              try{
                  System.out.println("Please enter something to kick off
        context closing");
                  String inStr = reader.readLine();
                  System.out.println("Input Data: "+inStr);

                  //including the line of code below will cause sleep waken up
                  //taking out the line below will not cause sleep waken up
                  dirContext.close();
              } catch (IOException ex){
                  ex.printStackTrace();
              } catch (Exception ex){
                  ex.printStackTrace();
              }

          }


          public static void main(String[] args){
              int val=0;
              TestSleep tester= null;
              try{
                  tester = new TestSleep();
                  System.out.println("Application starts now...");
                  val = Integer.parseInt(args[0]);

                  System.out.println("Main thread will sleep for "+val+"
        seconds...");
                  Thread.sleep(val*1000);
                  System.out.println("Main thread finished sleep!");
              } catch (InterruptedException ex) {
                  ex.printStackTrace();
              }

              System.out.println("Application ends now...");

          }
        }

        ------- End of file -------

        I searched your bug database before. There was a different, but very
        similar, bug before. I think it was accepted as bug and noted to have
        been fixed. My impression is it was filed against 1.4.x.

        But that bug was different from this one. As you said, that bug would
        show up whenever you changed the system clock through NTP and it caused
        the sleep() and wait() to wake up. I tried to follow that one in the
        same testing environment I had for testing my bug. I was not able to
        reproduce it. That means that bug was really fixed.

        For mine, you have to do a DirContext.close() to get the problem shown.
        Without that line of code, it will not have any problem.
        You can use my test program to verify by simply commenting out the
        close() line and you will not see it happen.

        From the test programs I provided, you can see that it does not have to
        be NTP. As long as you make the system call through clock_settime() you
        will see it.

        For the time being, we can do, actually we are doing, checking after the
        sleeping threads waken up and make sure it has slept enough time.
        Otherwise, we will put it back into sleep again. But as a general
        design/implementation, you should not wake up because a directory
        context is closed after system clock is adjusted. So, I can not buy that
        as an acceptable behavior.

        If a thread can wake up on all different kinds of unknown conditions
        prematurely, it will be very bad. Every time it wakes up it costs some
        resources even if you do make additional checking. Unless you publish a
        list of conditions which will cause the sleep() waken up before the
        time, application developers will not be able to avoid those. Then
        potentially, those waken up incidences can be VERY frequent. In that
        case, it will dramatically downgrade its performance. Do you think Java
        will still be a good business application development language?

        Unfortunately, I don't see any suggestions, in your API documentation
        for sleep(), that the time set when calling sleep() is only a hint and
        the thread can wake up any time for any unknown reasons. In my opinion,
        if any public classes' public methods have variable behavior depending
        on unknown conditions, its usefulness becomes very low since the users
        do not know how to deal with them. This is like if you have an engineer
        working for you and his behavior changes on many unknown conditions how
        difficult task it will be for his manager to manage this unreliable
        personnel.

              chrisphi Chris Phillips
              mhmiller Matt Miller (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: