rb_raise() causes segmentfault on xxxxx_alloc() function

  • Thread starter Iñaki Baz Castillo
  • Start date
I

Iñaki Baz Castillo

Hi, my C extension uses rb_define_alloc_func(cResolver,
Resolver_alloc) to initialite the C library. If something goes wrong
in that initialization I want to raise an exception but using
rb_raise() within Resolver_alloc() produces a segmentfault.

The function is very easy:

-------------------------------------------------------------------
VALUE Resolver_alloc(VALUE klass)
{
struct dns_ctx *dns_context;
VALUE obj;

if (dns_init(NULL, 0) < 0)
rb_raise(rb_eStandardError, "udns dns_init failed");

if (!(dns_context =3D dns_new(NULL)))
rb_raise(rb_eStandardError, "udns dns_new failed");

obj =3D Data_Wrap_Struct(klass, NULL, Resolver_free, dns_context);
return obj;
}
-------------------------------------------------------------------


In order to force the error I change the dns_init line as follows:

if (dns_init(NULL, 0) =3D=3D 0)

and get a segmentfault. Is not allowed to raise an exception in the
alloc function of a class?

Thanks.


--=20
I=C3=B1aki Baz Castillo
<[email protected]>
 
P

Peter Zotov

Hi, my C extension uses rb_define_alloc_func(cResolver,
Resolver_alloc) to initialite the C library. If something goes wrong
in that initialization I want to raise an exception but using
rb_raise() within Resolver_alloc() produces a segmentfault.
=20
The function is very easy:
=20
-------------------------------------------------------------------
VALUE Resolver_alloc(VALUE klass)
{
struct dns_ctx *dns_context;
VALUE obj;
=20
if (dns_init(NULL, 0) < 0)
rb_raise(rb_eStandardError, "udns dns_init failed");
=20
if (!(dns_context =3D dns_new(NULL)))
rb_raise(rb_eStandardError, "udns dns_new failed");
=20
obj =3D Data_Wrap_Struct(klass, NULL, Resolver_free, dns_context);
return obj;
}
-------------------------------------------------------------------
=20
=20
In order to force the error I change the dns_init line as follows:
=20
if (dns_init(NULL, 0) =3D=3D 0)
=20
and get a segmentfault. Is not allowed to raise an exception in the
alloc function of a class?
=20
Thanks.
=20
=20

I'm not exactly sure how this mechanism works (and udns too), but I'd
suggest:
a) If a C library needs an one-time initialization, implement that as a
class method of your Resolver class and call either on library loading
or on first use of the library (by defining a flag).
b) If a C library needs an initialization for each instance of the
object, just define initialize function for the class and do all the
initialization there; if you strictly need to do that in *_alloc
function(), try returning Qnil (I am not quite sure it will work at
all, but at least it's worth trying), or set a flag in the structure
you are returning. Either way will let you to determine whether to
raise an exception or not in the place where it's perfectly safe to do
that (the initialize function).

It looks to me that you need both approaches here.

--=20
WBR, Peter Zotov
 
I

Iñaki Baz Castillo

2011/2/7 Peter Zotov said:
I'm not exactly sure how this mechanism works (and udns too), but I'd
suggest:
a) If a C library needs an one-time initialization, implement that as a
class method of your Resolver class and call either on library loading
or on first use of the library (by defining a flag).
b) If a C library needs an initialization for each instance of the
object, just define initialize function for the class and do all the
initialization there; if you strictly need to do that in *_alloc
function(), try returning Qnil (I am not quite sure it will work at
all, but at least it's worth trying), or set a flag in the structure
you are returning. Either way will let you to determine whether to
raise an exception or not in the place where it's perfectly safe to do
that (the initialize function).

It looks to me that you need both approaches here.

Thanks a lot. I just need second approach as initialization of the C
library must occur for each instance.

I already tryed returning Qnil, and gives an ugly error:
`new': wrong instance allocation (TypeError)

So I took your second suggestion, but instead I set an attribute
@alloc_error during xxxx_alloc() function, and inspect it in normal
initialize() method (by raising if it is not nil).

Thanks a lot!

--=20
I=C3=B1aki Baz Castillo
<[email protected]>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top