Skip to content

Commit

Permalink
Propagate load error during require
Browse files Browse the repository at this point in the history
#1081

This is a temporary solution.  We need to repeat cleanup code
for `SCM_UNWIND_PROTECT` and error-trapping `Scm_Load` call, which
is awkward.

Better solution is with the line of #1079,
but that depends on continuation management overhaul.
  • Loading branch information
shirok committed Nov 26, 2024
1 parent fcf388f commit bc72409
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 14 deletions.
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
2024-11-25 Shiro Kawai <[email protected]>

* src/load.c (do_require): Use non-error-trapping Scm_Load when
PROPAGATE_ERROR is requrested.
https://github.com/shirok/Gauche/issues/1081

2024-11-24 Shiro Kawai <[email protected]>

* configure.ac: 0.9.15-p2, for reproducible "official" package.
Expand Down
49 changes: 35 additions & 14 deletions src/load.c
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,19 @@ int Scm_Require(ScmObj feature, int flags, ScmLoadPacket *packet)
return do_require(feature, flags, Scm__RequireBaseModule(), packet);
}

/* Called when load fails during require. We need to reset the providing
chain.*/
static inline void require_error_cleanup(ScmVM *vm,
ScmObj feature,
ScmModule *prev_mod)
{
vm->module = prev_mod;
(void)SCM_INTERNAL_MUTEX_LOCK(ldinfo.prov_mutex);
ldinfo.providing = Scm_AssocDeleteX(feature, ldinfo.providing, SCM_CMP_EQUAL);
(void)SCM_INTERNAL_COND_BROADCAST(ldinfo.prov_cv);
(void)SCM_INTERNAL_MUTEX_UNLOCK(ldinfo.prov_mutex);
}

int do_require(ScmObj feature, int flags, ScmModule *base_mod,
ScmLoadPacket *packet)
{
Expand Down Expand Up @@ -938,24 +951,32 @@ int do_require(ScmObj feature, int flags, ScmModule *base_mod,
}

if (!SCM_FALSEP(provided)) return 0; /* no work to do */
/* Make sure to load the file into base_mod. We don't need UNWIND_PROTECT
here, since errors are caught in Scm_Load. */
/* Make sure to load the file into base_mod. */
ScmLoadPacket xresult;
ScmModule *prev_mod = vm->module;
vm->module = base_mod;
int r = Scm_Load(Scm_GetStringConst(SCM_STRING(feature)), 0, &xresult);
vm->module = prev_mod;
if (packet) packet->exception = xresult.exception;

if (r < 0) {
/* Load failed */
(void)SCM_INTERNAL_MUTEX_LOCK(ldinfo.prov_mutex);
ldinfo.providing = Scm_AssocDeleteX(feature, ldinfo.providing, SCM_CMP_EQUAL);
(void)SCM_INTERNAL_COND_BROADCAST(ldinfo.prov_cv);
(void)SCM_INTERNAL_MUTEX_UNLOCK(ldinfo.prov_mutex);
if (flags&SCM_LOAD_PROPAGATE_ERROR) Scm_Raise(xresult.exception, 0);
else return -1;

/* A bit awkward, but if SCM_LOAD_PROPAGATE_ERROR is given, we don't
want to 'stop' the error, for we don't want to lose the stack trace.
*/
if (flags&SCM_LOAD_PROPAGATE_ERROR) {
SCM_UNWIND_PROTECT {
(void)Scm_Load(Scm_GetStringConst(SCM_STRING(feature)),
SCM_LOAD_PROPAGATE_ERROR, &xresult);
} SCM_WHEN_ERROR {
require_error_cleanup(vm, feature, prev_mod);
SCM_NEXT_HANDLER;
} SCM_END_PROTECT;
} else {
int r = Scm_Load(Scm_GetStringConst(SCM_STRING(feature)), 0, &xresult);
if (packet) packet->exception = xresult.exception;

if (r < 0) {
require_error_cleanup(vm, feature, prev_mod);
return -1;
}
}
vm->module = prev_mod;

/* Success */
(void)SCM_INTERNAL_MUTEX_LOCK(ldinfo.prov_mutex);
Expand Down

0 comments on commit bc72409

Please sign in to comment.