Fix a refcount bug.

This commit is contained in:
C. Guy Yarvin 2014-10-06 10:17:33 -07:00
parent 27c67acca4
commit 3c6398c106
9 changed files with 120 additions and 84 deletions

19
g/a.c
View File

@ -900,6 +900,25 @@ u3_ca_use(u3_noun som)
}
}
/* u3_ca_audit(): investigate object.
*/
c3_o
u3_ca_audit(u3_noun som)
{
if ( u3_so(u3_co_is_cat(som)) ) {
return u3_yes;
}
if ( 0 == u3_ca_use(som) ) {
u3_cm_p("som", som);
printf("zero: %x/%x\r\n", u3_cr_mug(som), som);
return u3_no;
}
else if ( u3_so(u3du(som)) ) {
return u3_and(u3_ca_audit(u3h(som)), u3_ca_audit(u3t(som)));
}
else return u3_yes;
}
/* u3_ca_slab(): create a length-bounded proto-atom.
*/
c3_w*

18
g/j.c
View File

@ -82,11 +82,10 @@ u3_cj_find(u3_noun bat)
{
u3_cs_road* rod_u = u3R;
while ( rod_u->par_u ) {
if ( u3_so(u3_co_is_senior(rod_u, bat)) ) {
rod_u = rod_u->par_u;
}
while ( rod_u->par_u && u3_so(u3_co_is_senior(rod_u, bat)) ) {
rod_u = rod_u->par_u;
}
{
u3_weak jax = u3_ch_get(rod_u->jed.har_u, bat);
@ -519,10 +518,8 @@ _cj_save(u3_noun bat,
u3_cs_road* rod_u = u3R;
u3_cs_road* tmp_u;
while ( rod_u->par_u ) {
if ( u3_so(u3_co_is_senior(rod_u, bat)) ) {
rod_u = rod_u->par_u;
}
while ( rod_u->par_u && u3_so(u3_co_is_senior(rod_u, bat)) ) {
rod_u = rod_u->par_u;
}
tmp_u = u3R;
@ -644,9 +641,10 @@ u3_cj_mine(u3_noun clu,
u3D.ray_u[jax_l].par_u = par_u;
c3_assert(0 != jax_l);
free(nam_c);
#if 0
fprintf(stderr, "mine: bound jet %d/%s\r\n",
cop_u->jax_l, cop_u->cos_c);
#endif
break;
}
i_l++;
@ -662,7 +660,7 @@ u3_cj_mine(u3_noun clu,
fak_u.axe_l = axe_l;
jax_l = _cj_insert(&fak_u);
fprintf(stderr, "mine: dummy jet %d/%s\r\n", jax_l, fak_u.cos_c);
// fprintf(stderr, "mine: dummy jet %d/%s\r\n", jax_l, fak_u.cos_c);
}
u3z(clu);

135
g/m.c
View File

@ -10,8 +10,7 @@
#include "all.h"
static jmp_buf Signal_u;
static c3_l Signal_l;
static jmp_buf u3_Signal;
#ifndef SIGSTKSZ
# define SIGSTKSZ 16384
@ -24,7 +23,7 @@ void u3_unix_ef_move(void); // restore system signal regime
extern void
u3_lo_sway(c3_l tab_l, u3_noun tax);
#if 1
#if 0
/* _cm_punt(): crudely print trace.
*/
static void
@ -53,19 +52,12 @@ _cm_emergency(c3_c* cap_c, c3_l sig_l)
write(2, "\r\n", 2);
}
static void _cm_overflow_over(void *arg1, void *arg2, void *arg3)
static void _cm_overflow(void *arg1, void *arg2, void *arg3)
{
(void)(arg1);
(void)(arg2);
(void)(arg3);
siglongjmp(Signal_u, c3__over);
}
static void _cm_overflow_dire(void *arg1, void *arg2, void *arg3)
{
(void)(arg1);
(void)(arg2);
(void)(arg3);
siglongjmp(Signal_u, c3__dire);
siglongjmp(u3_Signal, c3__over);
}
/* _cm_signal_handle(): handle a signal in general.
@ -73,33 +65,11 @@ static void _cm_overflow_dire(void *arg1, void *arg2, void *arg3)
static void
_cm_signal_handle(c3_l sig_l)
{
c3_l org_l = sig_l;
_cm_emergency("signal", sig_l);
if ( Signal_l || (u3R == &u3H->rod_u) ) {
_cm_emergency("signal overlap: old", Signal_l);
_cm_emergency("signal overlap: new", sig_l);
if ( c3__prof == sig_l ) {
// Ignore strange profiling event.
//
return;
}
sig_l = c3__dire;
}
Signal_l = sig_l;
if ( c3__over == org_l ) {
if ( c3__dire == sig_l ) {
sigsegv_leave_handler(_cm_overflow_dire, NULL, NULL, NULL);
}
else {
sigsegv_leave_handler(_cm_overflow_over, NULL, NULL, NULL);
}
if ( c3__over == sig_l ) {
sigsegv_leave_handler(_cm_overflow, NULL, NULL, NULL);
}
else {
siglongjmp(Signal_u, sig_l);
siglongjmp(u3_Signal, sig_l);
}
}
@ -118,6 +88,7 @@ _cm_signal_handle_term(int x)
static void
_cm_signal_handle_intr(int x)
{
abort();
_cm_signal_handle(c3__intr);
}
@ -140,21 +111,45 @@ _cm_signal_reset(void)
/* _cm_signal_recover(): recover from a deep signal, after longjmp.
*/
static u3_noun
_cm_signal_recover(void)
_cm_signal_recover(c3_l sig_l)
{
_cm_emergency("recover", Signal_l);
u3_noun tax;
if ( c3__dire == Signal_l ) {
Signal_l = 0;
// XX: special handling for profile signal.
//
// Unlikely to be set, but it can be made to happen.
//
tax = u3R->bug.tax;
u3R->bug.tax = 0;
if ( &(u3H->rod_u) == u3R ) {
// A top-level crash - rather odd. We should GC here.
//
_cm_emergency("recover: top", sig_l);
// Reset the top road - the problem could be a fat cap.
//
_cm_signal_reset();
return u3nt(3, c3__dire, 0);
if ( (c3__meme == sig_l) && (u3_co_open(u3R) <= 256) ) {
// Out of memory at the top level. Error becomes c3__full,
// and we release the emergency buffer. To continue work,
// we need to readjust the image, eg, migrate to 64 bit.
//
u3z(u3R->bug.mer);
sig_l = c3__full;
}
return u3nt(3, sig_l, tax);
}
else {
u3_noun tax = u3_nul;
u3_noun pro;
// Descend to the road that caused the problem - in almost all
// cases the innermost road, except for a
// A signal was generated while we were within Nock.
//
_cm_emergency("recover: dig", sig_l);
// Descend to the innermost trace, collecting stack.
//
{
u3_cs_road* rod_u;
@ -167,13 +162,12 @@ _cm_signal_recover(void)
rod_u = rod_u->kid_u;
}
}
u3_lo_sway(2, u3k(tax)); // XX
abort(); // XX
pro = u3nt(3, sig_l, tax);
_cm_signal_reset();
pro = u3nt(3, Signal_l, tax);
_cm_punt(tax);
u3_lo_sway(2, u3k(tax));
Signal_l = 0;
return pro;
}
}
@ -222,6 +216,14 @@ _cm_signal_done()
u3_unix_ef_move();
}
/* u3_cm_signal(): treat a nock-level exception as a signal interrupt.
*/
void
u3_cm_signal(u3_noun sig_l)
{
siglongjmp(u3_Signal, sig_l);
}
/* u3_cm_file(): load file, as atom, or bail.
*/
u3_noun
@ -323,6 +325,7 @@ _boot_parts(void)
{
u3R->cax.har_u = u3_ch_new();
u3R->jed.har_u = u3_ch_new();
u3R->bug.mer = u3_ci_tape("emergency buffer");
}
/* u3_cm_boot(): instantiate or activate image.
@ -417,7 +420,7 @@ u3_cm_bail(u3_noun how)
{
/* Printf some metadata.
*/
{
if ( c3__exit != how ) {
if ( u3_so(u3ud(how)) ) {
c3_c str_c[5];
@ -432,12 +435,26 @@ u3_cm_bail(u3_noun how)
c3_assert(u3_so(u3ud(u3h(how))));
fprintf(stderr, "bail: %d (at %llu)\r\n", u3h(how), u3N);
u3_cm_p("bail", u3t(how));
// u3_cm_p("bail", u3t(how));
}
}
// _cm_punt();
// u3_lo_sway(2, u3k(u3R->bug.tax));
abort();
// u3_cm_signal(c3__exit);
if ( c3__exit != how ) {
u3_lo_sway(2, u3k(u3R->bug.tax));
abort();
}
if ( &(u3H->rod_u) == u3R ) {
// For top-level errors, which shouln't happen often, we have no
// choice but to use the signal process; and we require the flat
// form of how.
//
c3_assert(u3_so(u3_co_is_cat(how)));
u3_cm_signal(how);
}
/* Reconstruct a correct error ball.
*/
@ -630,17 +647,20 @@ u3_cm_soft_top(c3_w sec_w, // timer seconds
{
u3_noun why, pro;
c3_w gof_w;
c3_l sig_l;
/* Enter internal signal regime.
*/
_cm_signal_deep(0);
if ( 0 != sigsetjmp(Signal_u, 1) ) {
if ( 0 != (sig_l = sigsetjmp(u3_Signal, 1)) ) {
// return to blank state
//
_cm_signal_done();
return _cm_signal_recover();
// recover memory state from the top down
//
return _cm_signal_recover(sig_l);
}
/* Record the cap, and leap.
@ -701,9 +721,6 @@ u3_cm_soft_run(u3_noun fly,
u3_noun why, pro;
c3_w gof_w;
u3_cm_wash(aga);
u3_cm_wash(agb);
/* Record the cap, and leap.
*/
{

1
g/n.c
View File

@ -379,6 +379,7 @@ u3_noun
u3_cn_nock_an(u3_noun bus, u3_noun fol)
{
u3_noun fly = u3nt(u3nc(1, 0), 0, 0); // |=(a=* ~)
u3_noun pro;
return u3_cn_nock_in(fly, bus, fol);
}

View File

@ -45,6 +45,11 @@
u3_noun
u3_ca_take(u3_noun som);
/* u3_ca_audit(): investigate object for bad refcounts.
*/
c3_o
u3_ca_audit(u3_noun som);
/* u3_ca_lose(): lose a reference.
*/
void

View File

@ -18,6 +18,11 @@
# define u3_cm_trap() (u3_noun)(setjmp(u3R->esc.buf))
#endif
/* u3_cm_signal(): treat a nock-level exception as a signal interrupt.
*/
void
u3_cm_signal(u3_noun sig_l);
/* u3_cm_bail(): bail out. Does not return.
**
** Bail motes:

View File

@ -144,12 +144,6 @@
c3_w fre_w; // number of free words
} all;
struct { // pseudo-interrupt
c3_l zap_l; // double signal, very bad
c3_l sig_l; // interrupt; written by signal
c3_l cry_l; // critical region, or 0
} coy;
struct { // jet dashboard
u3_ch_root* har_u; // jet index
} jed;
@ -160,6 +154,7 @@
struct { // trace stack
u3_noun tax; // (list ,*)
u3_noun mer; // emergency buffer to release
} bug;
struct { // profile stack

View File

@ -33,6 +33,7 @@
u3_noun fin = u3t(hoq);
if ( u3_nul == fin ) {
u3_cm_p("cog", cog);
return u3_cm_error("find-none");
}
else {

View File

@ -332,8 +332,7 @@ int FOO;
# define _mint_used()
static u3_noun
_mint_in(
u3_noun van,
_mint_in(u3_noun van,
u3_noun sut,
u3_noun gol,
u3_noun gen)
@ -388,8 +387,7 @@ int FOO;
if ( u3_yes == u3_cr_sing(rex, gen) ) {
#if 1
u3_noun zix = u3_cqfu_shep
(van, "gene", 'q', u3k(gen));
u3_noun zix = u3_cqfu_shep(van, "gene", 'q', u3k(gen));
u3_ct_push(u3nc(c3__mean, zix));
return u3_cm_error("mint-open");
@ -422,7 +420,7 @@ int FOO;
_mint_used();
{
u3_noun nob = u3_cqfl_bunt(van, p_gen);
u3_noun dok = u3nc(c3__cnzz, q_gen);
u3_noun dok = u3nc(c3__cnzz, u3k(q_gen));
u3_noun vol = _mint_corn(van, sut, dok);
u3_noun axe = _mint_coke(vol);
u3_noun wam = u3_cqfu_play(van, sut, nob);
@ -849,10 +847,7 @@ int FOO;
u3_noun hum = _mint_in(van, sut, gol, q_gen);
u3_noun bez = u3nt(c3__spot, 1, u3k(p_gen));
ret = u3nc(
u3k(u3h(hum)),
u3nt(10, bez, u3k(u3t(hum))));
ret = u3nc(u3k(u3h(hum)), u3nt(10, bez, u3k(u3t(hum))));
u3z(hum);
}
u3_ct_drop();