From: Lei Tang
Subject: How to automatically kill a function call after a long-time run?
Date: 
Message-ID: <eepkhr$8cm$1@news.asu.edu>
Hi, everyone.

I want to write some code to run some test cases by calling some 
functions(suppose "A"). However, "A" might take extremely long time if 
it doesn't do it efficiently. So I hope that my test-case code can 
automatically terminate the function call of A if it doesn't give me the 
result after some time (eg. 2 hours), so that I can check another test 
case.  Is there any way to do this in lisp? I really appreciate your help!!

-Lei

From: Pascal Bourguignon
Subject: Re: How to automatically kill a function call after a long-time run?
Date: 
Message-ID: <87odtba7pn.fsf@thalassa.informatimago.com>
Lei Tang <······@asu.edu> writes:

> Hi, everyone.
>
> I want to write some code to run some test cases by calling some
> functions(suppose "A"). However, "A" might take extremely long time if
> it doesn't do it efficiently. So I hope that my test-case code can
> automatically terminate the function call of A if it doesn't give me
> the result after some time (eg. 2 hours), so that I can check another
> test case.  Is there any way to do this in lisp? I really appreciate
> your help!!

[41]> (with-timeout (5 (print :timed-out))
       (loop :repeat 3
             :do (sleep 1) (princ ".") (finish-output) 
             :finally (return :done)))
...
:DONE
[42]> (with-timeout (5 (print :timed-out))
       (loop :repeat 10
             :do (sleep 1) (princ ".") (finish-output) 
             :finally (return :done)))
....
:TIMED-OUT 
:TIMED-OUT
[43]> 



;;;;**************************************************************************
;;;;FILE:               clisp--with-timeout.lisp
;;;;LANGUAGE:           Common-Lisp
;;;;SYSTEM:             Common-Lisp
;;;;USER-INTERFACE:     NONE
;;;;DESCRIPTION
;;;;    
;;;;    Testing SIGALRM on clisp on Linux.
;;;;    
;;;;AUTHORS
;;;;    <PJB> Pascal Bourguignon <···@informatimago.com>
;;;;MODIFICATIONS
;;;;    2006-05-02 <PJB> Added this header.
;;;;BUGS
;;;;LEGAL
;;;;    GPL
;;;;    
;;;;    Copyright Pascal Bourguignon 2006 - 2006
;;;;    
;;;;    This program is free software; you can redistribute it and/or
;;;;    modify it under the terms of the GNU General Public License
;;;;    as published by the Free Software Foundation; either version
;;;;    2 of the License, or (at your option) any later version.
;;;;    
;;;;    This program is distributed in the hope that it will be
;;;;    useful, but WITHOUT ANY WARRANTY; without even the implied
;;;;    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;;;;    PURPOSE.  See the GNU General Public License for more details.
;;;;    
;;;;    You should have received a copy of the GNU General Public
;;;;    License along with this program; if not, write to the Free
;;;;    Software Foundation, Inc., 59 Temple Place, Suite 330,
;;;;    Boston, MA 02111-1307 USA
;;;;**************************************************************************
;;;;    

(defun install-signal-handler (signum handler)
  (let ((oldhan (linux:|set-signal-handler| signum handler))
        (sigset (second (multiple-value-list
                         (linux:|sigaddset| (second (multiple-value-list
                                                     (linux:|sigemptyset|)))
                                signum)))))
    (linux:|sigprocmask-set-n-save| linux:|SIG_UNBLOCK| sigset)
    (values signum oldhan sigset)))


(defun restore-signal-handler (signum oldhan sigset)
  (linux:|set-signal-handler| signum oldhan)
  (linux:|sigprocmask-set-n-save| linux:|SIG_UNBLOCK| sigset))

  

(defmacro with-signal-handler (signum handler &body body)
  (let ((voldhan (gensym))
        (vsignum (gensym))
        (vsigset (gensym)))
    `(let* ((,vsignum ,signum)
            (,voldhan (linux:|set-signal-handler| ,vsignum ,handler))
            (,vsigset (second (multiple-value-list
                               (linux:|sigaddset| 
                                      (second (multiple-value-list
                                               (linux:|sigemptyset|)))
                                      ,vsignum)))))
       (linux:|sigprocmask-set-n-save| linux:|SIG_UNBLOCK| ,vsigset)
       (unwind-protect (progn ,@body)
         (linux:|set-signal-handler| ,vsignum ,voldhan)
         (linux:|sigprocmask-set-n-save| linux:|SIG_UNBLOCK| ,vsigset)))))


(defmacro with-sigseg-handler (&body body)
  `(with-signal-handler linux:|SIGSEGV| 
     (lambda (signum) 
       (declare (ignore signum))
       (error "Got Segment Violation Signal while accessing raw memory"))
     ,@body))


(defmacro with-timeout ((seconds &body timeout-forms) &body body)
  "
    This macro evaluates the body as a progn body. If the evaluation
    of body does not complete within the specified interval, execution
    throws out of the body and the timeout-forms are evaluated as a
    progn body, returning the result of the last form.)  The
    timeout-forms are not evaluated if the body completes within
    seconds.
    "
  (let ((timeout (gensym)))
    `(block ,timeout
       (with-signal-handler linux:|SIGALRM| 
         (lambda (signum) 
           (declare (ignore signum))
           (return-from ,timeout (progn ,@timeout-forms)))
         (LINUX:alarm ,seconds)
         (unwind-protect (progn ,@body)
           (LINUX:alarm 0))))))


;; Note: man 2 alarm warns against using sleep(2) and SIGALRM at the same time.
;;       Happily, it seems that on Linux they can be used together.


;; Local Variables:
;; eval: (cl-indent 'with-signal-handler 2)
;; End:



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

READ THIS BEFORE OPENING PACKAGE: According to certain suggested
versions of the Grand Unified Theory, the primary particles
constituting this product may decay to nothingness within the next
four hundred million years.
From: John Stoneham
Subject: Re: How to automatically kill a function call after a long-time run?
Date: 
Message-ID: <1158702761.456187.15020@b28g2000cwb.googlegroups.com>
I've had to do this in my current project. For a simple,
quick-and-dirty solution, at the start of your main computation loop
just set up a START-TIME variable with GET-UNIVERSAL-TIME, and update a
CURR-TIME variable with another call to GET-UNIVERSAL-TIME on each
iteration, and exit the loop when (>= (- curr-time start-time)
max-seconds).

Sort of like this:

(defun run-long (max-seconds)
     (do* ((start-time (get-universal-time))
	  (curr-time (start-time) (get-universal-time)))
	 ((>= (- curr-time start-time) max-seconds))
       ( ... stuff here ... )))

For a 2 hour cutoff, call with (run-long 7200).

For a more complete solution, look over Pascal's code.
From: Lei Tang
Subject: Re: How to automatically kill a function call after a long-time run?
Date: 
Message-ID: <eesj1d$kik$1@news.asu.edu>
Thanks a lot for your solution. But how to change it to a windows 
version? I tried to replace the "linux" with "windows" seems not work.

-Lei

Pascal Bourguignon wrote:
> Lei Tang <······@asu.edu> writes:
> 
> 
>>Hi, everyone.
>>
>>I want to write some code to run some test cases by calling some
>>functions(suppose "A"). However, "A" might take extremely long time if
>>it doesn't do it efficiently. So I hope that my test-case code can
>>automatically terminate the function call of A if it doesn't give me
>>the result after some time (eg. 2 hours), so that I can check another
>>test case.  Is there any way to do this in lisp? I really appreciate
>>your help!!
> 
> 
> [41]> (with-timeout (5 (print :timed-out))
>        (loop :repeat 3
>              :do (sleep 1) (princ ".") (finish-output) 
>              :finally (return :done)))
> ...
> :DONE
> [42]> (with-timeout (5 (print :timed-out))
>        (loop :repeat 10
>              :do (sleep 1) (princ ".") (finish-output) 
>              :finally (return :done)))
> ....
> :TIMED-OUT 
> :TIMED-OUT
> [43]> 
> 
> 
> 
> ;;;;**************************************************************************
> ;;;;FILE:               clisp--with-timeout.lisp
> ;;;;LANGUAGE:           Common-Lisp
> ;;;;SYSTEM:             Common-Lisp
> ;;;;USER-INTERFACE:     NONE
> ;;;;DESCRIPTION
> ;;;;    
> ;;;;    Testing SIGALRM on clisp on Linux.
> ;;;;    
> ;;;;AUTHORS
> ;;;;    <PJB> Pascal Bourguignon <···@informatimago.com>
> ;;;;MODIFICATIONS
> ;;;;    2006-05-02 <PJB> Added this header.
> ;;;;BUGS
> ;;;;LEGAL
> ;;;;    GPL
> ;;;;    
> ;;;;    Copyright Pascal Bourguignon 2006 - 2006
> ;;;;    
> ;;;;    This program is free software; you can redistribute it and/or
> ;;;;    modify it under the terms of the GNU General Public License
> ;;;;    as published by the Free Software Foundation; either version
> ;;;;    2 of the License, or (at your option) any later version.
> ;;;;    
> ;;;;    This program is distributed in the hope that it will be
> ;;;;    useful, but WITHOUT ANY WARRANTY; without even the implied
> ;;;;    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
> ;;;;    PURPOSE.  See the GNU General Public License for more details.
> ;;;;    
> ;;;;    You should have received a copy of the GNU General Public
> ;;;;    License along with this program; if not, write to the Free
> ;;;;    Software Foundation, Inc., 59 Temple Place, Suite 330,
> ;;;;    Boston, MA 02111-1307 USA
> ;;;;**************************************************************************
> ;;;;    
> 
> (defun install-signal-handler (signum handler)
>   (let ((oldhan (linux:|set-signal-handler| signum handler))
>         (sigset (second (multiple-value-list
>                          (linux:|sigaddset| (second (multiple-value-list
>                                                      (linux:|sigemptyset|)))
>                                 signum)))))
>     (linux:|sigprocmask-set-n-save| linux:|SIG_UNBLOCK| sigset)
>     (values signum oldhan sigset)))
> 
> 
> (defun restore-signal-handler (signum oldhan sigset)
>   (linux:|set-signal-handler| signum oldhan)
>   (linux:|sigprocmask-set-n-save| linux:|SIG_UNBLOCK| sigset))
> 
>   
> 
> (defmacro with-signal-handler (signum handler &body body)
>   (let ((voldhan (gensym))
>         (vsignum (gensym))
>         (vsigset (gensym)))
>     `(let* ((,vsignum ,signum)
>             (,voldhan (linux:|set-signal-handler| ,vsignum ,handler))
>             (,vsigset (second (multiple-value-list
>                                (linux:|sigaddset| 
>                                       (second (multiple-value-list
>                                                (linux:|sigemptyset|)))
>                                       ,vsignum)))))
>        (linux:|sigprocmask-set-n-save| linux:|SIG_UNBLOCK| ,vsigset)
>        (unwind-protect (progn ,@body)
>          (linux:|set-signal-handler| ,vsignum ,voldhan)
>          (linux:|sigprocmask-set-n-save| linux:|SIG_UNBLOCK| ,vsigset)))))
> 
> 
> (defmacro with-sigseg-handler (&body body)
>   `(with-signal-handler linux:|SIGSEGV| 
>      (lambda (signum) 
>        (declare (ignore signum))
>        (error "Got Segment Violation Signal while accessing raw memory"))
>      ,@body))
> 
> 
> (defmacro with-timeout ((seconds &body timeout-forms) &body body)
>   "
>     This macro evaluates the body as a progn body. If the evaluation
>     of body does not complete within the specified interval, execution
>     throws out of the body and the timeout-forms are evaluated as a
>     progn body, returning the result of the last form.)  The
>     timeout-forms are not evaluated if the body completes within
>     seconds.
>     "
>   (let ((timeout (gensym)))
>     `(block ,timeout
>        (with-signal-handler linux:|SIGALRM| 
>          (lambda (signum) 
>            (declare (ignore signum))
>            (return-from ,timeout (progn ,@timeout-forms)))
>          (LINUX:alarm ,seconds)
>          (unwind-protect (progn ,@body)
>            (LINUX:alarm 0))))))
> 
> 
> ;; Note: man 2 alarm warns against using sleep(2) and SIGALRM at the same time.
> ;;       Happily, it seems that on Linux they can be used together.
> 
> 
> ;; Local Variables:
> ;; eval: (cl-indent 'with-signal-handler 2)
> ;; End:
> 
> 
> 
From: Pascal Bourguignon
Subject: Re: How to automatically kill a function call after a long-time run?
Date: 
Message-ID: <873bam81hh.fsf@thalassa.informatimago.com>
Lei Tang <······@asu.edu> writes:

> Thanks a lot for your solution. But how to change it to a windows
> version? I tried to replace the "linux" with "windows" seems not work.

I don't know.  I know nothing about MS-Windows.

You'd have to learn about MS-Windows.  I hear Microsoft has a nice web
site gathering all the developer documentation about MS-Windows.

Then you could write FFI declarations in clisp to call MS-Windows
functions to implement the similar functionalities.  If you feel
generous, you could even contribute to clisp a MS-WINDOWS module
similar to the LINUX module ;-)

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Pour moi, la grande question n'a jamais �t�: �Qui suis-je? O� vais-je?� 
comme l'a formul� si adroitement notre ami Pascal, mais plut�t: 
�Comment vais-je m'en tirer?� -- Jean Yanne
From: Lei Tang
Subject: Re: How to automatically kill a function call after a long-time run?
Date: 
Message-ID: <eet1ru$l0p$1@news.asu.edu>
I am considering whether or not to switch to Linux:)
Seems windows is not a good choice for xemacs and lisp.

-Lei

Pascal Bourguignon wrote:
> Lei Tang <······@asu.edu> writes:
> 
> 
>>Thanks a lot for your solution. But how to change it to a windows
>>version? I tried to replace the "linux" with "windows" seems not work.
> 
> 
> I don't know.  I know nothing about MS-Windows.
> 
> You'd have to learn about MS-Windows.  I hear Microsoft has a nice web
> site gathering all the developer documentation about MS-Windows.
> 
> Then you could write FFI declarations in clisp to call MS-Windows
> functions to implement the similar functionalities.  If you feel
> generous, you could even contribute to clisp a MS-WINDOWS module
> similar to the LINUX module ;-)
> 
From: Pascal Bourguignon
Subject: Re: How to automatically kill a function call after a long-time run?
Date: 
Message-ID: <87y7sd7t02.fsf@thalassa.informatimago.com>
Lei Tang <······@asu.edu> writes:
> Pascal Bourguignon wrote:
>> Lei Tang <······@asu.edu> writes:
>> 
>>>Thanks a lot for your solution. But how to change it to a windows
>>>version? I tried to replace the "linux" with "windows" seems not work.
>> I don't know.  I know nothing about MS-Windows.
>> You'd have to learn about MS-Windows.  I hear Microsoft has a nice
>> web
>> site gathering all the developer documentation about MS-Windows.
>> Then you could write FFI declarations in clisp to call MS-Windows
>> functions to implement the similar functionalities.  If you feel
>> generous, you could even contribute to clisp a MS-WINDOWS module
>> similar to the LINUX module ;-)
>
> I am considering whether or not to switch to Linux:)
> Seems windows is not a good choice for xemacs and lisp.

At the same time you might consider switching to bottom posting too.


-- 
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
----------> http://www.netmeister.org/news/learn2quote.html <-----------
---> http://homepage.ntlworld.com/g.mccaughan/g/remarks/uquote.html <---

__Pascal Bourguignon__                     http://www.informatimago.com/
From: John Thingstad
Subject: Re: How to automatically kill a function call after a long-time run?
Date: 
Message-ID: <op.tf7rwgvzpqzri1@pandora.upc.no>
On Thu, 21 Sep 2006 05:46:40 +0200, Lei Tang <······@asu.edu> wrote:

> I am considering whether or not to switch to Linux:)
> Seems windows is not a good choice for xemacs and lisp.
>
> -Lei
>
> Pascal Bourguignon wrote:
>> Lei Tang <······@asu.edu> writes:
>>
>>> Thanks a lot for your solution. But how to change it to a windows
>>> version? I tried to replace the "linux" with "windows" seems not work.
>>   I don't know.  I know nothing about MS-Windows.
>>  You'd have to learn about MS-Windows.  I hear Microsoft has a nice web
>> site gathering all the developer documentation about MS-Windows.
>>  Then you could write FFI declarations in clisp to call MS-Windows
>> functions to implement the similar functionalities.  If you feel
>> generous, you could even contribute to clisp a MS-WINDOWS module
>> similar to the LINUX module ;-)
>>

xemacs is never a good choice use emacs.
As for Windows and Lisp the comecial versions are ok.
ACL rules if you can afford it.
Unix belongs in a museum :)

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Jock Cooper
Subject: Re: How to automatically kill a function call after a long-time run?
Date: 
Message-ID: <87k63rizw5.fsf@mail.com>
Lei Tang <······@asu.edu> writes:

> Hi, everyone.
> 
> I want to write some code to run some test cases by calling some
> functions(suppose "A"). However, "A" might take extremely long time if
> it doesn't do it efficiently. So I hope that my test-case code can
> automatically terminate the function call of A if it doesn't give me
> the result after some time (eg. 2 hours), so that I can check another
> test case.  Is there any way to do this in lisp? I really appreciate
> your help!!
> 
> -Lei

You could use the multiprocessing package and run the function as a
process.  Then the main process could kill the process if it runs too
long.  However it isn't really safe to kill a process that way (for
example, if the kill occurs while the process is processing unwind
forms).  

I have found it is safest have the to function cooperate by
terminating itself.  Your processes can communicate using structures
such as MP:QUEUE and MP:GATE (ACL has these, not sure if other CLs
do).  And of course judicious use of macros can make this scheme as
unobtrusive as needed.