caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Matching exceptions in C code
@ 2017-06-03  6:44 Richard W.M. Jones
  2017-06-21 15:39 ` Richard W.M. Jones
  0 siblings, 1 reply; 4+ messages in thread
From: Richard W.M. Jones @ 2017-06-03  6:44 UTC (permalink / raw)
  To: caml-list

I'm trying to catch a Unix_error exception in C code, and extract the
errno from it.  Getting the errno is fine, but the problem is matching
on the Unix.Unix_error exception.

My original code used the documented method:

  retv = caml_callbackN_exn (*cb, 4, args);

  if (Is_exception_result (retv)) {
    retv = Extract_exception (retv);
    if (Field (retv, 0) == *caml_named_value ("Unix.Unix_error"))
      ...

However the if statement never matched the exception.  (I verified on
the OCaml side that the correct exception is being thrown).

After reading:

  http://caml.inria.fr/pub/ml-archives/caml-list/2006/05/097f63cfb39a80418f95c70c3c520aa8.en.html
  http://caml.inria.fr/pub/ml-archives/caml-list/2009/06/797e2f797f57b8ea2a2c0e431a2df312.en.html

it seems I'm not the first person to have this problem.  It may be
that Unix is linked twice, but I'm not really sure about that.  I'm
using -output-obj with unix.cmxa linked into the object file, and also
-lunix in the link step, which is the documented way to do things, but
I don't know if that means the Unix module initializes itself twice.

Anyway, I modified the code to this, which *works* and is actually
more convenient than the documented method (the real code matches on
several other system exceptions as well):

    ...
    retv = Extract_exception (retv);
    exn_name = String_val (Field (Field (retv, 0), 0));
    if (strcmp (exn_name, "Unix.Unix_error") == 0) {
      int errcode = code_of_unix_error (Field (retv, 1));

The questions are:

(a) Will this continue to work in future?  It seems to be
undocumented.

(b) Could we have some sort of official function to hide the details?

Rich.

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

* Re: [Caml-list] Matching exceptions in C code
  2017-06-03  6:44 [Caml-list] Matching exceptions in C code Richard W.M. Jones
@ 2017-06-21 15:39 ` Richard W.M. Jones
  2017-06-21 15:50   ` John Whitington
  0 siblings, 1 reply; 4+ messages in thread
From: Richard W.M. Jones @ 2017-06-21 15:39 UTC (permalink / raw)
  To: caml-list

On Sat, Jun 03, 2017 at 07:44:31AM +0100, Richard W.M. Jones wrote:
> I'm trying to catch a Unix_error exception in C code, and extract the
> errno from it.  Getting the errno is fine, but the problem is matching
> on the Unix.Unix_error exception.
> 
> My original code used the documented method:
> 
>   retv = caml_callbackN_exn (*cb, 4, args);
> 
>   if (Is_exception_result (retv)) {
>     retv = Extract_exception (retv);
>     if (Field (retv, 0) == *caml_named_value ("Unix.Unix_error"))
>       ...
> 
> However the if statement never matched the exception.  (I verified on
> the OCaml side that the correct exception is being thrown).
> 
> After reading:
> 
>   http://caml.inria.fr/pub/ml-archives/caml-list/2006/05/097f63cfb39a80418f95c70c3c520aa8.en.html
>   http://caml.inria.fr/pub/ml-archives/caml-list/2009/06/797e2f797f57b8ea2a2c0e431a2df312.en.html
> 
> it seems I'm not the first person to have this problem.  It may be
> that Unix is linked twice, but I'm not really sure about that.  I'm
> using -output-obj with unix.cmxa linked into the object file, and also
> -lunix in the link step, which is the documented way to do things, but
> I don't know if that means the Unix module initializes itself twice.
> 
> Anyway, I modified the code to this, which *works* and is actually
> more convenient than the documented method (the real code matches on
> several other system exceptions as well):
> 
>     ...
>     retv = Extract_exception (retv);
>     exn_name = String_val (Field (Field (retv, 0), 0));
>     if (strcmp (exn_name, "Unix.Unix_error") == 0) {
>       int errcode = code_of_unix_error (Field (retv, 1));

So I found out today that this doesn't work for every exception.

For 'End_of_file' in particular, 'exn_name' ends up pointing to a bit
of random memory (unfortunately it's not NULL or otherwise easily
detectable), and so the program crashes in the strcmp.

I'm still interested in the answers to the questions below ...

> The questions are:
> 
> (a) Will this continue to work in future?  It seems to be
> undocumented.
> 
> (b) Could we have some sort of official function to hide the details?

Rich.

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

* Re: [Caml-list] Matching exceptions in C code
  2017-06-21 15:39 ` Richard W.M. Jones
@ 2017-06-21 15:50   ` John Whitington
  2017-06-21 16:06     ` Richard W.M. Jones
  0 siblings, 1 reply; 4+ messages in thread
From: John Whitington @ 2017-06-21 15:50 UTC (permalink / raw)
  To: Richard W.M. Jones; +Cc: caml-list

Hi.

> On 21 Jun 2017, at 16:39, Richard W.M. Jones <rich@annexia.org> wrote:
> 
> On Sat, Jun 03, 2017 at 07:44:31AM +0100, Richard W.M. Jones wrote:
>> I'm trying to catch a Unix_error exception in C code, and extract the
>> errno from it.  Getting the errno is fine, but the problem is matching
>> on the Unix.Unix_error exception.
>> 
>> My original code used the documented method:
>> 
>>  retv = caml_callbackN_exn (*cb, 4, args);
>> 
>>  if (Is_exception_result (retv)) {
>>    retv = Extract_exception (retv);
>>    if (Field (retv, 0) == *caml_named_value ("Unix.Unix_error"))
>>      ...
>> 
>> However the if statement never matched the exception.  (I verified on
>> the OCaml side that the correct exception is being thrown).
>> 
>> After reading:
>> 
>>  http://caml.inria.fr/pub/ml-archives/caml-list/2006/05/097f63cfb39a80418f95c70c3c520aa8.en.html
>>  http://caml.inria.fr/pub/ml-archives/caml-list/2009/06/797e2f797f57b8ea2a2c0e431a2df312.en.html
>> 
>> it seems I'm not the first person to have this problem.  It may be
>> that Unix is linked twice, but I'm not really sure about that.  I'm
>> using -output-obj with unix.cmxa linked into the object file, and also
>> -lunix in the link step, which is the documented way to do things, but
>> I don't know if that means the Unix module initializes itself twice.
>> 
>> Anyway, I modified the code to this, which *works* and is actually
>> more convenient than the documented method (the real code matches on
>> several other system exceptions as well):
>> 
>>    ...
>>    retv = Extract_exception (retv);
>>    exn_name = String_val (Field (Field (retv, 0), 0));
>>    if (strcmp (exn_name, "Unix.Unix_error") == 0) {
>>      int errcode = code_of_unix_error (Field (retv, 1));
> 
> So I found out today that this doesn't work for every exception.
> 
> For 'End_of_file' in particular, 'exn_name' ends up pointing to a bit
> of random memory (unfortunately it's not NULL or otherwise easily
> detectable), and so the program crashes in the strcmp.

End_of_file, Invalid_argument, and Failure are not defined in pervasives.ml, they are “internal” in some sense. Perhaps this is the cause?

John

-- 
John Whitington
Director, Coherent Graphics Ltd


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

* Re: [Caml-list] Matching exceptions in C code
  2017-06-21 15:50   ` John Whitington
@ 2017-06-21 16:06     ` Richard W.M. Jones
  0 siblings, 0 replies; 4+ messages in thread
From: Richard W.M. Jones @ 2017-06-21 16:06 UTC (permalink / raw)
  To: John Whitington; +Cc: caml-list

On Wed, Jun 21, 2017 at 04:50:06PM +0100, John Whitington wrote:
> >>    retv = Extract_exception (retv);
> >>    exn_name = String_val (Field (Field (retv, 0), 0));
> >>    if (strcmp (exn_name, "Unix.Unix_error") == 0) {
> >>      int errcode = code_of_unix_error (Field (retv, 1));
> > 
> > So I found out today that this doesn't work for every exception.
> > 
> > For 'End_of_file' in particular, 'exn_name' ends up pointing to a bit
> > of random memory (unfortunately it's not NULL or otherwise easily
> > detectable), and so the program crashes in the strcmp.
> 
> End_of_file, Invalid_argument, and Failure are not defined in pervasives.ml, they are “internal” in some sense. Perhaps this is the cause?

Actually it's not a random pointer, it's a pointer made of ASCII
characters.  In other words it seems there is one less indirection.
This code works for me:

  if (Tag_val (Field (exn, 0)) == String_tag)
    exn_name = String_val (Field (exn, 0));    // for End_of_file
  else
    exn_name = String_val (Field (Field (exn, 0), 0));  // for others

but I feel like I'm well outside the bounds of valid, supportable use
of the OCaml VM here.

Rich.

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

end of thread, other threads:[~2017-06-21 16:07 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-03  6:44 [Caml-list] Matching exceptions in C code Richard W.M. Jones
2017-06-21 15:39 ` Richard W.M. Jones
2017-06-21 15:50   ` John Whitington
2017-06-21 16:06     ` Richard W.M. Jones

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).