Welcome guest. Before posting on our computer help forum, you must register. Click here it's easy and free.

Author Topic: How to set a time limit for program execution  (Read 21615 times)

0 Members and 1 Guest are viewing this topic.

Salmon Trout

  • Guest
Re: How to set a time limit for program execution
« Reply #15 on: July 22, 2010, 11:53:02 AM »
IF you ping a non-existent address then it will always take the maximum timeout.

But localhost exists. The default wait is 1 second, but the exception to this is the last packet.  As soon as PING receives the last packet sent, it will stop. Since the local loopback is being pinged, the reply is nearly instaneous.

Quote
I'm pretty sure that it won't work with localhost.

The "ping localhost timer trick" is so well known, I'm surprised you query it. It has been posted countless times on this forum. You add 1 to the number of seconds you want.

It's not exact, as you can see...

Code: [Select]
@echo off
echo %time%
ping -n 11 127.0.0.1>nul
echo %time%

Code: [Select]
S:\Test\Batch\>ptimer1.cmd
18:43:00.20
18:43:10.26

S:\Test\Batch\>ptimer1.cmd
18:43:12.52
18:43:22.57

S:\Test\Batch\>ptimer1.cmd
18:43:25.62
18:43:35.67

S:\Test\Batch\>ptimer1.cmd
18:43:44.16
18:43:54.21


Salmon Trout

  • Guest
Re: How to set a time limit for program execution
« Reply #16 on: July 22, 2010, 12:23:16 PM »
(1) The ping command cannot be used to achieve a specific delay. The -n option specifies the number of echo requests to send, and the -w option specifies the timeout in milliseconds to wait for each reply. Thus, there is no guarantee that the time to execute the ping is n*w milliseconds. It can take shorter or longer time.

See above. Localhost is pingable with a fairly consistent delay of less than 1 ms.

Code: [Select]
Pinging 127.0.0.1 with 32 bytes of data:
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128

hels

    Topic Starter


    Rookie

    Re: How to set a time limit for program execution
    « Reply #17 on: July 22, 2010, 03:46:02 PM »
    Thanks you everybody for the comments. The code below almost works as intended. The time limit is actually close to 120 seconds (not 100 seconds), but I can live with that.

    However, there are still two defects:

    (1) The exit status from the Solver program (0 or 1) can not be tested. If it is 0, the batch program should continue by executing the Tester program; otherwise, it should finish.
    (2) The taskkill command always gives a message. I want to get rid of that message.

    Any ideas?

    @echo off
    if EXIST tmp del tmp
    echo %1 %2
    start /B java Solver %3/%1 %3/%2 > tmp
    set i=0

    :repeat
    ping -n 2 localhost > nul
    tasklist|find "java.exe"> nul
    if %ERRORLEVEL% NEQ 0 goto :test
    set /a i=%i%+1
    echo %i%
    if %i% LSS 100 goto repeat

    taskkill /f /im java.exe
    echo *** Solution not found within 100 seconds
    goto end

    :test
    java Tester %3/%1 %3/%2 < tmp
    if %ERRORLEVEL% NEQ 0 echo *** Incorrect solver output
    :end
    if EXIST tmp del tmp
    echo.

    BC_Programmer


      Mastermind
    • Typing is no substitute for thinking.
    • Thanked: 1140
      • Yes
      • Yes
      • BC-Programming.com
    • Certifications: List
    • Computer: Specs
    • Experience: Beginner
    • OS: Windows 11
    Re: How to set a time limit for program execution
    « Reply #18 on: July 22, 2010, 03:48:15 PM »
    Doesn't Java have it's own set of packages/utilities in the SDK for performing Unit tests?

    I was trying to dereference Null Pointers before it was cool.

    hels

      Topic Starter


      Rookie

      Re: How to set a time limit for program execution
      « Reply #19 on: July 22, 2010, 06:06:17 PM »
      Hi BC_Programmer,

      The Solver programs to be run by the DOS prompt are made by my students, not me. Their program should call System.exit(1), if the puzzle to be solved has no solution.

      Below is the UNIX script that does the job. I am a bit surprised that it can be that difficult with DOS.

      echo "Checking a puzzle in 100 seconds"
      ulimit -t 100
      testdir=$3
      /bin/rm -f /tmp/out$$
      echo $1 " " $2
      java Solver $testdir/$1 $testdir/$2 > /tmp/out$$
      if test "$?" -ne 0
      then
          echo "*** Wrong exit status"
      fi
      java Tester $testdir/$1 $testdir/$2 < /tmp/out$$
      if test "$?" -ne 0
      then
          echo "*** Incorrect solver output"
      fi
      /bin/rm -f /tmp/out$$
      echo " "
       

      hels

        Topic Starter


        Rookie

        Re: How to set a time limit for program execution
        « Reply #20 on: July 22, 2010, 11:41:14 PM »
        I have made a test that demonstrates that the suggested approach does not work. When I ran the DOS prompt shown below the output was:

        7:18:31,71
        7:20:32,56

        That is, it took about 120 seconds when it should have been 100. I can accept this error. However, when I removed the REM from the second line, in which Test is the infinity loop Java program

                 class Test { public static void main(String[] args) { while(true); } }

        I got

        7:25:56,96
        7:34:39,07

        That is, it took almost 9 minutes! I find this error unacceptable.   

        ---------------------------

        @echo off
        REM start /B java Test
        echo %time%
        set i=0
        :repeat
        ping -n 2 localhost > nul
        tasklist | find "java.exe" > nul
        set /a i=%i%+1
        if %i% LSS 100 goto repeat
        echo %time%
        pause

        Salmon Trout

        • Guest
        Re: How to set a time limit for program execution
        « Reply #21 on: July 23, 2010, 12:04:54 AM »
        I find this error unacceptable.   

        Your language is odd; this is not an "error"; it is the result of your code.

        BC_Programmer


          Mastermind
        • Typing is no substitute for thinking.
        • Thanked: 1140
          • Yes
          • Yes
          • BC-Programming.com
        • Certifications: List
        • Computer: Specs
        • Experience: Beginner
        • OS: Windows 11
        Re: How to set a time limit for program execution
        « Reply #22 on: July 23, 2010, 03:43:43 AM »
        I'm sure it's possible to do this with batch, but it seems... sort of hacky, since you can load java classes natively in any java applications.

        With that, I decided to try my hand at creating a small program designed for limiting the time that a given java console application can run. to my surprise, it seems to work great.

        The basic idea is simple- use reflection to load a class name specified on the command line, find the main() method, create a new thread that invokes that method, put the first thread to sleep for the specified timeout period (not <exact> but probably closer then using ping...) and, check the state of the started thread after Sleep() returns; if the thread has terminated, the program finished, (or, there was an error running it, which will have be displayed). If not, the thread is still running and has failed to complete in the specified timeout. At that point, it is forced to stop with the stop() method (yes, I know, it's deprecated, but it's either that or leave it running in the background which especially in the case of my test program (which was just a for(;;);) meant that the CPU/a core was throttled to 100%.

        Anyway, enough of that banter. The program itself consists of two classes:"javatest" which is the main program, and another class, "methodInvoker" which implements Runnable to allow for the second thread.

        javatest.java:
        Code: [Select]
        import java.io.*;
        import java.lang.reflect.*;
        import java.net.*;
        import java.util.*;
        import java.io.*;
        public class javatest{
        /*
         * arguments: classname timeout <args to pass to class>
         *
         *
         *
         */
        static String join(String[] passpathparts, String delimiter) {
            StringBuilder builder = new StringBuilder();
            for(int i = 0;i<passpathparts.length;i++)
            {
            builder.append(passpathparts[i]);
            if(i<passpathparts.length-1)
            builder.append(delimiter);
           
           
            }
            return builder.toString();
        }


        private static Class loadclassfromfile(String filename)
        {
        File file = new File(filename);


        try {
           // Convert File to a URL
         

           
           String[] splitpathparts = filename.split("\\\\");
           
           String[] passpathparts = new String[splitpathparts.length-1];
           System.arraycopy(splitpathparts, 1, passpathparts, 0, splitpathparts.length-1);
           
           String[] justpatharr = new String[splitpathparts.length-1];
           System.arraycopy(splitpathparts, 0, justpatharr, 0, splitpathparts.length-1);
           
           File dirpath = new File(join(justpatharr,"\\")+ "\\");
           URL url = dirpath.toURI().toURL();          // file:/c:/myclasses/
           URL[] urls = new URL[]{url};

           // Create a new class loader with the directory
           //
           ClassLoader cl = new URLClassLoader(urls);
           
           
           
           String classloadstring = join(passpathparts,".");
           System.out.println("loading class..." + classloadstring);
           // Load in the class; MyClass.class should be located in
           // the directory file:/c:/myclasses/com/mycompany
           Class returnme = cl.loadClass(classloadstring);
           return returnme;
           //Class cls = cl.loadClass("com.mycompany.MyClass");
        } catch (MalformedURLException e) {
        } catch (ClassNotFoundException e) {
        }

        return null;




        }
        public static void main(String[] args)
        {
        Thread runmethodthread=null;
        if(args.length<2)
        {
        System.out.println("must pass at least 2 arguments");
        return;
        }
        int timeout = Integer.parseInt(args[0]);
        String[] passargs=new String[args.length-2];
        System.arraycopy(args, 2, passargs, 0, args.length-2);
        try{
        java.lang.Class c;
        if((new File(args[1] + ".class").exists() ))
        {
        c = loadclassfromfile(args[1]);
        }
        else
        {
        c = Class.forName(args[1]);
        }
        Method m[] = c.getDeclaredMethods();
        Method mainmethod;
                for (int i = 0; i < m.length; i++)
                   if(m[i].getName().equals("main"))
                    {
                    mainmethod = m[i];
                    runmethodthread = new java.lang.Thread(new methodinvoker(m[i],passargs));
                    break;
                   
                    }
               
                if(runmethodthread!=null)
                {
               
                runmethodthread.start();
                System.out.println("Waiting " + timeout + " seconds for " + args[1] + "...");
                Thread.sleep(timeout*1000);
                if(runmethodthread.getState()==Thread.State.TERMINATED)
                {
               
                System.out.println("class " + args[1] + " has successfully completed.");
               
                }
                else
                {
                System.out.println("class " + args[1] + " did not complete in the timeout period.");
                runmethodthread.stop();
               
                }
               
               
                }
               
        }
                catch (Throwable e) {
                    System.err.println(e);
                 }




        }



        }

        methodinvoker.java

        Code: [Select]
        import java.lang.reflect.Method;

        public class methodinvoker implements Runnable
        {
        private Method mMethodInvoke;
        private String[] args;
        public methodinvoker(Method invokethis,String[] arguments)
        {
        mMethodInvoke=invokethis;
        args = arguments;

        }
        @Override
        public void run() {
        try{
        Object[] objargs ={args};
        mMethodInvoke.invoke(null, objargs);
        }

        catch(Exception e)
        {
        if(e.getMessage()!=null)
        System.out.println("error:" + e.getMessage()) ;


        }
        finally{

        }
        }
        }




        basically, once you've successfully compiled them (I'm using JDK version 1.6.0_17) you just need to start the javatest program with the proper arguments, such as:

        java javatest 15 D:\folder\folder\classfile <arguments>

        where <arguments> will be the arguments to pass on to the "main(String[] args)" routine of the specified class (from your batch and Unix scripts examples I am guessing that you are indeed passing something to these "Solver" programs). Also of note is that while it's quite possible to do so I was lazy and it only works when the specified classfile has a main() routine that accepts String[] args... that is, you cannot use this with a class that uses a main() routine without any arguments.

        You might need to tweak the multiplier used in the call to Thread.sleep(), I didn't actually measure it but it seemed to take longer then 15 seconds when I passed 15, but I could have been imagining things.

        I was trying to dereference Null Pointers before it was cool.

        hels

          Topic Starter


          Rookie

          Re: How to set a time limit for program execution
          « Reply #23 on: July 23, 2010, 05:07:47 AM »
          Thanks BC_programmer for your constructive suggestion.

          Running the Solver in another Java thread is of course a possibility, but it seems to me that it is like shooting sparrows with cannons.

          Suppose the Solver program was written in another language than Java. What to do in this case? It would be nice to have a general and working procedure for setting a time limit for a program.   

          BC_Programmer


            Mastermind
          • Typing is no substitute for thinking.
          • Thanked: 1140
            • Yes
            • Yes
            • BC-Programming.com
          • Certifications: List
          • Computer: Specs
          • Experience: Beginner
          • OS: Windows 11
          Re: How to set a time limit for program execution
          « Reply #24 on: July 23, 2010, 05:52:38 AM »
          Suppose the Solver program was written in another language than Java.
          It would be nice to have a general and working procedure for setting a time limit for a program.   
          yep, the little thing I cooked up might be the start of something to that effect, It's certainly possible to change it to execute any application with a timeout (heck, it would have probably been easier for me to do it that way, but I felt like messing about with Reflection for some reason). I might give that a try now, actually.
          I was trying to dereference Null Pointers before it was cool.

          hels

            Topic Starter


            Rookie

            Re: How to set a time limit for program execution
            « Reply #25 on: July 23, 2010, 07:59:10 AM »
            I have worked a bit more with my previous test batch file .

            As suggested by mat123 I downloaded the sleep.exe utility and replaced the ping command with "sleep 1". This helped a bit. But I now discovered that the culprit is the command "tasklist | find "java.exe" >nul". Even though it is only executed once every second, it is a real "time killer". If took 7 minutes to run the batch file below. Without the command, it took 2 minutes. I wonder if there is a faster way to test if a program is still running.

            @echo off
            start /B java Test
            echo %time%
            set i=0
            :repeat
            sleep 1
            tasklist | find "java.exe" >nul
            set /a i=%i%+1
            if %i% LSS 100 goto repeat
            echo %time%
            pause

            Sidewinder



              Guru

              Thanked: 139
            • Experience: Familiar
            • OS: Windows 10
            Re: How to set a time limit for program execution
            « Reply #26 on: July 23, 2010, 09:51:42 AM »
            This space is available. I realized my "solution" would not work with a job that runs within the command processor.

             8)
            « Last Edit: July 23, 2010, 10:19:49 AM by Sidewinder »
            The true sign of intelligence is not knowledge but imagination.

            -- Albert Einstein

            mat123



              Hopeful

              Thanked: 16
              • Yes
              • Yes
              • Yes
            • Experience: Familiar
            • OS: Windows XP
            Re: How to set a time limit for program execution
            « Reply #27 on: July 23, 2010, 11:14:09 AM »
            task list find "java.exe"
            takes less than one second
            Code: [Select]
            10:16:48.80
            10:16:49.12
            10:16:49.38
            10:16:49.67
            10:16:49.95
            10:16:50.21
            10:16:50.57
            10:16:50.87
            10:16:51.14
            10:16:51.40
            10:16:51.67
            10:16:52.01
            10:16:52.26
            10:16:52.51
            10:16:52.77
            10:16:53.02
            10:16:53.28
            10:16:53.54
            10:16:53.83
            10:16:54.10



            Salmon Trout

            • Guest
            Re: How to set a time limit for program execution
            « Reply #28 on: July 23, 2010, 11:36:40 AM »
            task list find "java.exe"
            takes less than one second

            Around 70 mS on my system

            Code: [Select]
            @echo off
            setlocal enabledelayedexpansion
            for /l %%N in (1,1,10) do (
            echo !time!
            tasklist | find "explorer.exe">nul
            echo !time!
            echo.
            )
            pause



            Code: [Select]
            18:35:56.20
            18:35:56.27

            18:35:56.27
            18:35:56.35

            18:35:56.35
            18:35:56.43

            18:35:56.43
            18:35:56.50

            18:35:56.50
            18:35:56.58

            18:35:56.58
            18:35:56.66

            18:35:56.66
            18:35:56.73

            18:35:56.74
            18:35:56.82

            18:35:56.82
            18:35:56.89

            18:35:56.89
            18:35:56.97


            Salmon Trout

            • Guest
            Re: How to set a time limit for program execution
            « Reply #29 on: July 23, 2010, 12:19:43 PM »
            There are several programs called sleep.exe around. The one I have has a -m switch which allows you specify the delay in milliseconds. If you have this version (easy to find out, just do sleep /? at the prompt) you can fine-tune the delay in the loop to achieve a repetion rate of 1 per second on a particular machine.

            The version hosted on Computerhope does not have the -m switch and gives this help message

            Code: [Select]
            F:\Download>sleep /?

            Arguments are: Sleep <seconds>

            www.tricerat.com

            The version in the Windows 2003 Resource Kit does have it - the kit is contained in rktools.exe, a self extracting archive.

            http://www.microsoft.com/downloads/details.aspx?familyid=9d467a69-57ff-4ae7-96ee-b18c4790cffd&displaylang=en

            Code: [Select]
            C:\utils\Utility Suites\win2K3 Reskit\Tools>sleep /?
            Usage:  sleep      time-to-sleep-in-seconds
                    sleep [-m] time-to-sleep-in-milliseconds
                    sleep [-c] commited-memory ratio (1%-100%)