(defmacro with-timeout (timeout &rest forms)
"Signals system::simple-interrupt-condition after <timeout> seconds."
(let ((result (gensym)))
`(let ((child-pid (linux:fork)))
(if (eql 0 child-pid)
(progn (sleep ,timeout) ;child
(linux:kill (linux:getppid) 14)
(linux:_exit 0))
(let ((,result (progn ,@forms))) ;parent
(linux:kill child-pid 9)
,result)))))
I loose the slime-connection if I use it without catching the
condition.
So what happens if a SIGINT or a SIGALRM comes while the timeout
is ticking? Probably you think you have a timeout, then a new
condition pops up a while later. The macro should may be be
changed so it unconditionally kills the child.
I am sure there are some other problems too.
Anyway, test:
(handler-case (with-timeout 3
(sleep 2)
:ended)
(system::simple-interrupt-condition (c) :timed-out))
=> :ENDED
(handler-case (with-timeout 1
(sleep 2)
:ended)
(system::simple-interrupt-condition (c) :timed-out))
=> :TIMED-OUT
Johan Ur Riise wrote:
> (let ((,result (progn ,@forms))) ;parent
> (linux:kill child-pid 9)
> ,result)))))
Users of macros with body-forms arguments that advertise answering of
the value of the last form usually expect answering of the *values* of
the last form. See MULTIPLE-VALUE-LIST, VALUES-LIST, and
MULTIPLE-VALUE-PROG1 for ways to implement this behavior in the
parent-process case.
--
Stephen Compall
http://scompall.nocandysw.com/blog
Stephen Compall wrote:
> Johan Ur Riise wrote:
> > (let ((,result (progn ,@forms))) ;parent
> > (linux:kill child-pid 9)
> > ,result)))))
>
> Users of macros with body-forms arguments that advertise answering of
> the value of the last form usually expect answering of the *values* of
> the last form. See MULTIPLE-VALUE-LIST, VALUES-LIST, and
> MULTIPLE-VALUE-PROG1 for ways to implement this behavior in the
> parent-process case.
Two birds, one stone:
(unwind-protect (progn ,@forms) (linux:kill child-pid 9))
"Kaz Kylheku" <········@gmail.com> writes:
> Stephen Compall wrote:
> > Johan Ur Riise wrote:
> > > (let ((,result (progn ,@forms))) ;parent
> > > (linux:kill child-pid 9)
> > > ,result)))))
> >
> > Users of macros with body-forms arguments that advertise answering of
> > the value of the last form usually expect answering of the *values* of
> > the last form. See MULTIPLE-VALUE-LIST, VALUES-LIST, and
> > MULTIPLE-VALUE-PROG1 for ways to implement this behavior in the
> > parent-process case.
>
> Two birds, one stone:
>
> (unwind-protect (progn ,@forms) (linux:kill child-pid 9))
Ok, now it reads:
(defmacro with-timeout (timeout &rest forms)
"Signals system::simple-interrupt-condition after <timeout> seconds.
Note: you might loose the connection with slime if you dont catch it"
(let ((result (gensym)))
`(let ((child-pid (linux:fork)))
(if (eql 0 child-pid)
(progn (sleep ,timeout) ;child
(linux:kill (linux:getppid) 14)
(linux:_exit 0))
(unwind-protect (progn ,@forms)
(linux:kill child-pid 9))))))
;; test
(handler-case (with-timeout .3 (sleep .2) :ended)
(system::simple-interrupt-condition (c) :timed-out))
(handler-case (with-timeout .1 (sleep .2) :ended)
(system::simple-interrupt-condition (c) :timed-out))
Johan Ur Riise <·····@riise-data.no> writes:
> "Kaz Kylheku" <········@gmail.com> writes:
>
> > Stephen Compall wrote:
> > > Johan Ur Riise wrote:
> > > > (let ((,result (progn ,@forms))) ;parent
> > > > (linux:kill child-pid 9)
> > > > ,result)))))
> > >
> > > Users of macros with body-forms arguments that advertise answering of
> > > the value of the last form usually expect answering of the *values* of
> > > the last form. See MULTIPLE-VALUE-LIST, VALUES-LIST, and
> > > MULTIPLE-VALUE-PROG1 for ways to implement this behavior in the
> > > parent-process case.
> >
> > Two birds, one stone:
> >
> > (unwind-protect (progn ,@forms) (linux:kill child-pid 9))
>
> Ok, now it reads:
Using c.l.l as my source code management system...
#+clisp
(defmacro with-timeout (timeout &rest forms)
"Signals system::simple-interrupt-condition after <timeout> seconds.
Note: you might loose the connection with slime if you dont catch it"
(let ((child-pid (gensym)))
`(let ((,child-pid (linux:fork)))
(if (eql 0 ,child-pid)
(progn (sleep ,timeout) ;child
(linux:kill (linux:getppid) 14)
(linux:_exit 0))
(unwind-protect (progn ,@forms) ;parent
(linux:kill ,child-pid 9))))))
;; test
(handler-case (with-timeout .3 (sleep .2) :ended)
(system::simple-interrupt-condition () :timed-out))
=> :ENDED
(handler-case (with-timeout .1 (sleep .2) :ended)
(system::simple-interrupt-condition () :timed-out))
=> :TIMED-OUT