Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
* how to set breakpoint at exception throw?
@ 2000-06-28 23:24 Scott McPeak
  2000-06-30 13:08 ` Xavier Leroy
  0 siblings, 1 reply; 13+ messages in thread
From: Scott McPeak @ 2000-06-28 23:24 UTC (permalink / raw)
  To: caml-list


In the debugger, I'd like to put a breakpoint essentially in the
'raise' function.  The idea is to get control whenever an exception is
raised, and be able to take a backtrace.

Any ideas on how to do this?

Note: I'm mainly interested in exceptions thrown by the runtime
(e.g. stack overflow), not those thrown by my own code, so simply
wrapping every 'raise' is not enough.

-Scott




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: how to set breakpoint at exception throw?
  2000-06-28 23:24 how to set breakpoint at exception throw? Scott McPeak
@ 2000-06-30 13:08 ` Xavier Leroy
  2000-07-01 12:57   ` Gerd Stolpmann
  2000-07-05  1:28   ` Scott McPeak
  0 siblings, 2 replies; 13+ messages in thread
From: Xavier Leroy @ 2000-06-30 13:08 UTC (permalink / raw)
  To: Scott McPeak, caml-list

> In the debugger, I'd like to put a breakpoint essentially in the
> 'raise' function.  The idea is to get control whenever an exception is
> raised, and be able to take a backtrace.
> Any ideas on how to do this?

Reverse execution is your friend: simply run the program under the
debugger; if an uncaught exception causes the program to terminate,
back-step (command "back") once, and voila, you're at the point where
the exception was raised, and you can examine the backtrace.

If your program traps all exceptions or performs finalization before
re-raising exceptions, you may have to back-step several times, but
eventually you'll hit the point where the exception was raised.

- Xavier Leroy



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: how to set breakpoint at exception throw?
  2000-06-30 13:08 ` Xavier Leroy
@ 2000-07-01 12:57   ` Gerd Stolpmann
  2000-07-03 15:05     ` Patrick M Doane
  2000-07-05  1:28   ` Scott McPeak
  1 sibling, 1 reply; 13+ messages in thread
From: Gerd Stolpmann @ 2000-07-01 12:57 UTC (permalink / raw)
  To: Xavier Leroy, Scott McPeak, caml-list

On Fri, 30 Jun 2000, Xavier Leroy wrote:
>> [Scott McPeak:] In the debugger, I'd like to put a breakpoint essentially in
>> the 'raise' function.  The idea is to get control whenever an exception is
>> raised, and be able to take a backtrace.
>> Any ideas on how to do this?
>
>Reverse execution is your friend: simply run the program under the
>debugger; if an uncaught exception causes the program to terminate,
>back-step (command "back") once, and voila, you're at the point where
>the exception was raised, and you can examine the backtrace.
>
>If your program traps all exceptions or performs finalization before
>re-raising exceptions, you may have to back-step several times, but
>eventually you'll hit the point where the exception was raised.

This debugging technique should be mentioned in the manual; it is important
enough.

Does reverse execution also work for programs doing I/O, for example reading
from a pipe?

Nevertheless, I have a wish: At least for programs compiled with the bytecode
compiler, an automatic backtrace of uncaught exceptions would be often helpful
(i.e I get a list where the last uncaught exception was raised, and all
locations where it is re-raised in the "with" clause of the "try" statement).
First, this type of error is very frequent, and it would save much time if the
location where the problem occurs were output from the failing program itself.
Second, under some environments it is difficult to run the debugger; not every
program is run from the command-line (CGI programs, for example). Furthermore,
such a feature would help bug searching in production environments: on such
machines, there is usually no debugger installed, and it is sometimes difficult
to reconstruct the failing data case.

For me, such a feature would be more worth than the loss of execution
performance of exceptions. I can imagine that it might be even possible to turn
such a feature dynamically on or off (by setting a hook in the bytecode
interpreter).

For multi-threaded programs, it is sufficient to store the list of uncaught
exceptions for every thread, and to output the list of the failing thread.

Gerd
-- 
----------------------------------------------------------------------------
Gerd Stolpmann      Telefon: +49 6151 997705 (privat)
Viktoriastr. 100             
64293 Darmstadt     EMail:   gerd@gerd-stolpmann.de
Germany                     
----------------------------------------------------------------------------



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: how to set breakpoint at exception throw?
  2000-07-01 12:57   ` Gerd Stolpmann
@ 2000-07-03 15:05     ` Patrick M Doane
  2000-07-03 21:43       ` Norman Ramsey
  2000-07-04 14:43       ` John Max Skaller
  0 siblings, 2 replies; 13+ messages in thread
From: Patrick M Doane @ 2000-07-03 15:05 UTC (permalink / raw)
  To: Gerd Stolpmann; +Cc: Xavier Leroy, Scott McPeak, caml-list

On Sat, 1 Jul 2000, Gerd Stolpmann wrote:

> Nevertheless, I have a wish: At least for programs compiled with the bytecode
> compiler, an automatic backtrace of uncaught exceptions would be often helpful
> (i.e I get a list where the last uncaught exception was raised, and all
> locations where it is re-raised in the "with" clause of the "try" statement).
> First, this type of error is very frequent, and it would save much time if the
> location where the problem occurs were output from the failing program itself.
> Second, under some environments it is difficult to run the debugger; not every
> program is run from the command-line (CGI programs, for example). Furthermore,
> such a feature would help bug searching in production environments: on such
> machines, there is usually no debugger installed, and it is sometimes difficult
> to reconstruct the failing data case.

I agree strongly that such a feature is needed for Ocaml development. I
have lost a lot of time to tracking down these problems in the past and
this is one of the few weak points in using the language right now.

Patrick



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: how to set breakpoint at exception throw?
  2000-07-03 15:05     ` Patrick M Doane
@ 2000-07-03 21:43       ` Norman Ramsey
  2000-07-06  3:05         ` Michael Hohn
  2000-07-04 14:43       ` John Max Skaller
  1 sibling, 1 reply; 13+ messages in thread
From: Norman Ramsey @ 2000-07-03 21:43 UTC (permalink / raw)
  To: caml-list

Let me add my voice to the crowd: if the default behavior of a failing
caml program were to produce a trace of uncaught exceptions, my life
would be easier.  It will be especially helpful when we start shipping
buggy caml programs to unsuspecting users, who can't reasonably be
asked to run the caml debugger...


Norman



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: how to set breakpoint at exception throw?
  2000-07-03 15:05     ` Patrick M Doane
  2000-07-03 21:43       ` Norman Ramsey
@ 2000-07-04 14:43       ` John Max Skaller
  2000-07-04 18:19         ` Gerd Stolpmann
  1 sibling, 1 reply; 13+ messages in thread
From: John Max Skaller @ 2000-07-04 14:43 UTC (permalink / raw)
  To: Patrick M Doane; +Cc: Gerd Stolpmann, Xavier Leroy, Scott McPeak, caml-list

Patrick M Doane wrote:
> 
> On Sat, 1 Jul 2000, Gerd Stolpmann wrote:
> 
> > Nevertheless, I have a wish: At least for programs compiled with the bytecode
> > compiler, an automatic backtrace of uncaught exceptions would be often helpful
> > (i.e I get a list where the last uncaught exception was raised, and all
> > locations where it is re-raised in the "with" clause of the "try" statement).
> > First, this type of error is very frequent, and it would save much time if the
> > location where the problem occurs were output from the failing program itself.
> > Second, under some environments it is difficult to run the debugger; not every
> > program is run from the command-line (CGI programs, for example). Furthermore,
> > such a feature would help bug searching in production environments: on such
> > machines, there is usually no debugger installed, and it is sometimes difficult
> > to reconstruct the failing data case.
> 
> I agree strongly that such a feature is needed for Ocaml development. I
> have lost a lot of time to tracking down these problems in the past and
> this is one of the few weak points in using the language right now.
> 
> Patrick

Hmmmm. I don't know how to do this in ocaml, but in C++ and Python it is
easy:
you create an exception one of whose components is the caught exception,
and throw it, thus preserving the whole exception chain. That is, you
can do
this in user space without special system support.

-- 
John (Max) Skaller, mailto:skaller@maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
checkout Vyper http://Vyper.sourceforge.net
download Interscript http://Interscript.sourceforge.net



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: how to set breakpoint at exception throw?
  2000-07-04 14:43       ` John Max Skaller
@ 2000-07-04 18:19         ` Gerd Stolpmann
  2000-07-05 22:13           ` Jean-Christophe Filliatre
                             ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Gerd Stolpmann @ 2000-07-04 18:19 UTC (permalink / raw)
  To: John Max Skaller, Patrick M Doane; +Cc: Xavier Leroy, Scott McPeak, caml-list

On Tue, 04 Jul 2000, John Max Skaller wrote:
>> On Sat, 1 Jul 2000, Gerd Stolpmann wrote:
>> 
>> > Nevertheless, I have a wish: At least for programs compiled with the bytecode
>> > compiler, an automatic backtrace of uncaught exceptions would be often helpful
>> > (i.e I get a list where the last uncaught exception was raised, and all
>> > locations where it is re-raised in the "with" clause of the "try" statement).
>> > First, this type of error is very frequent, and it would save much time if the
>> > location where the problem occurs were output from the failing program itself.
>> > Second, under some environments it is difficult to run the debugger; not every
>> > program is run from the command-line (CGI programs, for example). Furthermore,
>> > such a feature would help bug searching in production environments: on such
>> > machines, there is usually no debugger installed, and it is sometimes difficult
>> > to reconstruct the failing data case.
>
>Hmmmm. I don't know how to do this in ocaml, but in C++ and Python it is
>easy:
>you create an exception one of whose components is the caught exception,
>and throw it, thus preserving the whole exception chain. That is, you
>can do
>this in user space without special system support.

In general, you are right; the problem is that I do not have access to the
location in the source code where the exception happened. I'm interested in the
line number and the file name of the statement that originally caused the
exception. Example:

try 
  try
    raise Not_found
  with
    x ->
      (* XXX: Clean-up code here *)
      raise x
with
  x ->
    (* XXX: Clean-up code here *)
    raise x

which would cause the following backtrace:

Uncaught exception: Not_found
Exception backtrace:
- File x, line 3: Not_found
- File x, line 7: Not_found
- File x, line 11: Not_found

One can imagine having a user space "raise" function:

let exception_list := ref []

let alt_raise exc =
  exception_list := (caller.file_name, caller.line_number, exc) ::
                    !exception_list;
  raise exc

Problems: First, there is no "caller" information available without additional
help of the compiler. Second, I want to reset exception_list whenever the "with"
clause returns a regular result. (The latter is a simplification: only the last
uninterrupted chain of exceptions is reported. I think this is sufficient for
debugging.)

My proposal is to modify the bytecode compiler/interpreter such that every
"raise" bytecode statement has access to the location of the exception, and
that (optionally) the bytecode interpreter adds the exception to the
exception_list, or resets this list (this would require an additional bytecode
statement). This would not change the representation of exceptions, and it
would cost minimal extra execution time (the exception_list could be represented
as array with an upper limit).

I do not suggest to modify the native compiler in the same way, because it
would cost (relatively) much more time than for the bytecode system.

Gerd
-- 
----------------------------------------------------------------------------
Gerd Stolpmann      Telefon: +49 6151 997705 (privat)
Viktoriastr. 100             
64293 Darmstadt     EMail:   gerd@gerd-stolpmann.de
Germany                     
----------------------------------------------------------------------------



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: how to set breakpoint at exception throw?
  2000-06-30 13:08 ` Xavier Leroy
  2000-07-01 12:57   ` Gerd Stolpmann
@ 2000-07-05  1:28   ` Scott McPeak
  1 sibling, 0 replies; 13+ messages in thread
From: Scott McPeak @ 2000-07-05  1:28 UTC (permalink / raw)
  To: Xavier Leroy; +Cc: caml-list


> > In the debugger, I'd like to put a breakpoint essentially in the
> > 'raise' function.  The idea is to get control whenever an exception is
> > raised, and be able to take a backtrace.
> > Any ideas on how to do this?
> 
> Reverse execution is your friend: simply run the program under the
> debugger; if an uncaught exception causes the program to terminate,
> back-step (command "back") once, and voila, you're at the point where
> the exception was raised, and you can examine the backtrace.
> 
> If your program traps all exceptions or performs finalization before
> re-raising exceptions, you may have to back-step several times, but
> eventually you'll hit the point where the exception was raised.

I tried this and it took me a while to get it right, in particular
because I was using Printexc.catch to catch it at toplevel, and
several places did catch-and-rethrow.  So I thought I'd summarize:

The key was to run it in the debugger, let it say "uncaught
exception", then "back" once.  This puts you in Printexc.catch's code.  
Now do "previous", which backsteps across fn calls, until the
execution point (denoted by "<|a|>" or "<|b|>") is at the start of the
"with" block.  Then "back" to get to the next throw point, "previous"
again to the top of the block, etc.  You have to use "back" to get
from "with" to "raise" -- if you do "previous" it will go haywire; you
have to use "previous" to step across fn calls in the "with" block
because otherwise it takes forever.

But, I'd like to chime in on the side of advocating more support from
the debugger and/or compiler on getting backtraces.  A start would be
a stand-alone fn to retrieve a backtrace in the code itself, and then
a convention about including backtraces in exception objects.  (And oh
yeah, line/col instead of (or in addition to) char offsets would be
nice.)

-Scott




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: how to set breakpoint at exception throw?
  2000-07-04 18:19         ` Gerd Stolpmann
@ 2000-07-05 22:13           ` Jean-Christophe Filliatre
  2000-07-06  1:26           ` Max Skaller
  2000-07-06 11:23           ` Daniel de Rauglaudre
  2 siblings, 0 replies; 13+ messages in thread
From: Jean-Christophe Filliatre @ 2000-07-05 22:13 UTC (permalink / raw)
  To: gerd
  Cc: John Max Skaller, Patrick M Doane, Xavier Leroy, Scott McPeak, caml-list


> In general, you are right; the  problem is that I do not have access
> to the location in the source code where the exception happened. I'm
> interested in  the line  number and the  file name of  the statement
> that originally caused the exception. Example:

It should  be easy to do  with camlp4, since locations  in sources are
bound in the right hand sides of grammar rules. Thus, you just have to
overwrite the syntax of raise so that it actually raises the exception
together with its location, in an exception looking like

  exception LocatedException of exn * (int * int);;

Then, when you want to debug  your program, you compile it with camlp4
and that little extension, instead of ocamlc.

I'm not expert enough  in the use of camlp4 to give  the code for this
extension (by the way, there is no quotation for raising exception, as
far as I looked in the manual) but I'm sure that's no more than two or
three lines of  code. And I don't know if the  current file name being
parsed can be accessed. Surely Daniel will be of some help here if you
ask him.

-- 
Jean-Christophe Filliatre    
  Computer Science Laboratory   Phone (650) 859-5173
  SRI International             FAX   (650) 859-2844
  333 Ravenswood Ave.           email filliatr@csl.sri.com
  Menlo Park, CA 94025, USA     web   http://www.csl.sri.com/~filliatr

  



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: how to set breakpoint at exception throw?
  2000-07-04 18:19         ` Gerd Stolpmann
  2000-07-05 22:13           ` Jean-Christophe Filliatre
@ 2000-07-06  1:26           ` Max Skaller
  2000-07-06 11:23           ` Daniel de Rauglaudre
  2 siblings, 0 replies; 13+ messages in thread
From: Max Skaller @ 2000-07-06  1:26 UTC (permalink / raw)
  To: gerd
  Cc: John Max Skaller, Patrick M Doane, Xavier Leroy, Scott McPeak, caml-list

Gerd Stolpmann wrote:

> In general, you are right; the problem is that I do not have access to the
> location in the source code where the exception happened. I'm interested in the
> line number and the file name of the statement that originally caused the
> exception. 

	Ah. Yes, in C you can get the current line number with a __LINE__
macro.
(And in C++, this creates havoc for the One Definition Rule :-)

-- 
John (Max) Skaller at OTT [Open Telecommications Ltd]
mailto:maxs@in.ot.com.au      -- at work
mailto:skaller@maxtal.com.au  -- at home



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: how to set breakpoint at exception throw?
  2000-07-03 21:43       ` Norman Ramsey
@ 2000-07-06  3:05         ` Michael Hohn
  0 siblings, 0 replies; 13+ messages in thread
From: Michael Hohn @ 2000-07-06  3:05 UTC (permalink / raw)
  To: caml-list


Norman Ramsey <nr@eecs.harvard.edu> wrote:
>> ...
>> 
>>    Let me add my voice to the crowd: if the default behavior of a failing
>>    caml program were to produce a trace of uncaught exceptions, my life
>>    would be easier.
>> ...

Yes!  Support for this would help greatly, especially in the toplevel
where the debugger is not available.

Mike



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: how to set breakpoint at exception throw?
  2000-07-04 18:19         ` Gerd Stolpmann
  2000-07-05 22:13           ` Jean-Christophe Filliatre
  2000-07-06  1:26           ` Max Skaller
@ 2000-07-06 11:23           ` Daniel de Rauglaudre
  2 siblings, 0 replies; 13+ messages in thread
From: Daniel de Rauglaudre @ 2000-07-06 11:23 UTC (permalink / raw)
  To: Gerd Stolpmann
  Cc: John Max Skaller, Patrick M Doane, Xavier Leroy, Scott McPeak, caml-list

Hello,

On Tue, Jul 04, 2000 at 08:19:20PM +0200, Gerd Stolpmann wrote:

> Uncaught exception: Not_found
> Exception backtrace:
> - File x, line 3: Not_found
> - File x, line 7: Not_found
> - File x, line 11: Not_found

Can't camlp4 help you?

========================================= file toto.ml
open Pcaml

EXTEND
  expr: LEVEL "apply"
    [ [ "myraise"; e = expr LEVEL "simple" ->
          let bp = <:expr< $int:string_of_int (fst loc)$ >> in
          let ep = <:expr< $int:string_of_int (snd loc)$ >> in
          <:expr< raise (LocExc $e$ $str:!input_file$ ($bp$, $ep$)) >> ] ]
  ;
END
=========================================

$ ocamlc -pp "camlp4o pa_extend.cmo q_MLast.cmo" -I `camlp4 -where` -c toto.ml

========================================= file foo.ml
exception LocExc of exn * string * (int * int)

try 
  try
    myraise Not_found
  with
    x ->
      (* XXX: Clean-up code here *)
      myraise x
with
  x ->
    (* XXX: Clean-up code here *)
    myraise x
=========================================

$ ocamlc -c -pp "camlp4o ./toto.cmo" foo.ml

$ camlp4o ./toto.cmo pr_o.cmo foo.ml
exception LocExc of exn * string * (int * int);;

try
  try raise (LocExc (Not_found, "foo.ml", (63, 80))) with
    x -> raise (LocExc (x, "foo.ml", (139, 148)))
with
  x -> raise (LocExc (x, "foo.ml", (199, 208)));;

-- 
Daniel de RAUGLAUDRE
daniel.de_rauglaudre@inria.fr
http://cristal.inria.fr/~ddr/



^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: how to set breakpoint at exception throw?
@ 2000-07-05 21:29 Don Syme
  0 siblings, 0 replies; 13+ messages in thread
From: Don Syme @ 2000-07-05 21:29 UTC (permalink / raw)
  To: 'Norman Ramsey', caml-list

For what it's worth, some sort of indication of where execution was when a
stack overflow happens would also be great. 

Cheers,
Don

-----Original Message-----
From: Norman Ramsey [mailto:nr@eecs.harvard.edu]
Sent: 03 July 2000 22:44
To: caml-list@inria.fr
Subject: Re: how to set breakpoint at exception throw? 


Let me add my voice to the crowd: if the default behavior of a failing
caml program were to produce a trace of uncaught exceptions, my life
would be easier.  It will be especially helpful when we start shipping
buggy caml programs to unsuspecting users, who can't reasonably be
asked to run the caml debugger...


Norman



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2000-07-07 14:33 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-06-28 23:24 how to set breakpoint at exception throw? Scott McPeak
2000-06-30 13:08 ` Xavier Leroy
2000-07-01 12:57   ` Gerd Stolpmann
2000-07-03 15:05     ` Patrick M Doane
2000-07-03 21:43       ` Norman Ramsey
2000-07-06  3:05         ` Michael Hohn
2000-07-04 14:43       ` John Max Skaller
2000-07-04 18:19         ` Gerd Stolpmann
2000-07-05 22:13           ` Jean-Christophe Filliatre
2000-07-06  1:26           ` Max Skaller
2000-07-06 11:23           ` Daniel de Rauglaudre
2000-07-05  1:28   ` Scott McPeak
2000-07-05 21:29 Don Syme

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox