c - Safely freeing resources in XS code (running destructors on scope exit) -
i writing xs module. allocate resource (e.g. malloc()
or svrefcnt_inc()
) operations involving perl api, free resource. fine in normal c because c has no exceptions, code using perl api may croak()
, preventing normal cleanup , leaking resources. therefore seems impossible write correct xs code except simple cases.
when croak()
myself can clean resources allocated far, may calling functions croak()
directly sidestep cleanup code write.
pseudo-code illustrate concern:
static void some_other_function(pthx_ data* d) { ... if (perhaps) croak("could not frobnicate data"); } module = example package = example void xs(uv n) code: { /* allocate resources needed function */ data* object_graph; newx(object_graph, 1, data); data_init(object_graph, n); /* call functions use perl api */ some_other_function(athx_ object_graph); /* clean before returning. * not run if above code croak()s! * can put xs equivalent of "try...finally" block? */ data_destroy(object_graph); safefree(object_graph); }
so how safely clean resources in xs code? how can register destructor run when exceptions thrown, or when return xs code perl code?
my ideas , findings far:
i can create class runs necessary cleanup in destructor, create mortal sv containing instance of class. @ point in future perl free sv , run destructor. however, seems rather backwards, , there has better way.
xsawyerx's xs fun booklet seems discuss destroy methods @ great length, not handling of exceptions originate within xs code.
leont's
scope::onexit
module features xs code usingsavedestructor()
,savedestructor_x()
macros. these not seem documented.the perl api lists
save_destructor()
,save_destructor_x()
functions public undocumented.perl's
scope.h
header (includedperl.h
) declaressavedestructor(f,p)
,savedestructor_x(f,p)
macros, without further explanation. judging context ,scope::onexit
code,f
function pointer ,p
void pointer passedf
. _x version functions declaredpthx_
macro parameter.
am on right track this? should use these macros appropriate? in perl version introduced? there further guidance available on use? when precisely destructors triggered? presumably @ point related freetmps
or leave
macros?
upon further research, turns out savedestructor
in fact documented – in perlguts rather perlapi. exact semantics documented there.
i therefore assume savedestructor
supposed used "finally" block cleanup, , sufficiently safe , stable.
excerpt localizing changes in perlguts, discusses equivalent { local $foo; ... }
blocks:
there way achieve similar task c via perl api: create pseudo-block, , arrange changes automatically undone @ end of it, either explicit, or via non-local exit (via die()). block-like construct created pair of
enter
/leave
macros (see returning scalar in perlcall). such construct may created specially important localized task, or existing 1 (like boundaries of enclosing perl subroutine/block, or existing pair freeing tmps) may used. (in second case overhead of additional localization must negligible.) note xsub automatically enclosed inenter
/leave
pair.inside such pseudo-block following service available:
[…]
savedestructor(destructorfunc_nocontext_t f, void *p)
at end of pseudo-block function
f
called argumentp
.
savedestructor_x(destructorfunc_t f, void *p)
at end of pseudo-block function
f
called implicit context argument (if any), ,p
.
the section lists couple of specialized destructors, savefreesv(sv *sv)
, savemortalizesv(sv *sv)
may more correct premature sv_2mortal()
in cases.
these macros have been available since forever, @ least perl 5.6 or older.
Comments
Post a Comment