Skip to content

Commit ba824b1

Browse files
committed
FIX: allow extension context handles to reference other Rebol resources and so keep it safe from GC
1 parent 0c3ef44 commit ba824b1

File tree

4 files changed

+42
-20
lines changed

4 files changed

+42
-20
lines changed

src/core/c-handle.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@
138138
hob->sym = sym;
139139
CLEAR(hob->data, size);
140140
USE_HOB(hob);
141-
//printf("HOB made mem: %p\n", hob->data);
141+
//printf("HOB %p made mem: %p\n", hob, hob->data);
142142
return hob;
143143
}
144144

src/core/f-extension.c

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ x*/ RXIARG Value_To_RXI(REBVAL *val)
9898
case RXE_HANDLE:
9999
arg.addr = VAL_HANDLE(val);
100100
arg.handle.type = VAL_HANDLE_TYPE(val);
101+
arg.handle.flags = VAL_HANDLE_FLAGS(val);
101102
break;
102103
case RXE_32:
103104
arg.int32a = VAL_I32(val);

src/core/m-gc.c

+2-3
Original file line numberDiff line numberDiff line change
@@ -324,13 +324,12 @@ static void Mark_Series(REBSER *series, REBCNT depth);
324324
//printf("marked hob: %p %p\n", hob, val);
325325
MARK_HANDLE_CONTEXT(val);
326326
if (hob->series) {
327-
//puts("marked hob's series");
328-
MARK_SERIES(hob->series);
327+
Mark_Series(hob->series, depth);
329328
}
330329
}
331330
else if (IS_SERIES_HANDLE(val) && !HANDLE_GET_FLAG(val, HANDLE_RELEASABLE)) {
332331
//printf("markserhandle %0xh val: %0xh %s \n", (void*)val, VAL_HANDLE(val), VAL_HANDLE_NAME(val));
333-
MARK_SERIES(VAL_HANDLE_DATA(val));
332+
Mark_Series(VAL_HANDLE_DATA(val), depth);
334333
}
335334
break;
336335

src/os/host-ext-test.c

+38-16
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ extern RL_LIB *RL; // Link back to reb-lib from embedded extensions
5454
static REBCNT Handle_XTest;
5555
typedef struct XTest_Context {
5656
REBCNT id;
57-
REBINT num;
57+
REBCNT flags;
5858
} XTEST;
5959

6060
u32* x_arg_words;
@@ -113,13 +113,13 @@ char *RX_Spec =
113113
"vec0: command [{return vector size in bytes} v [vector!]]\n"
114114
"vec1: command [{return vector size in bytes (from object)} o [object!]]\n"
115115
"blk1: command [{print type ids of all values in a block} b [block!]]\n"
116-
"hob1: command [{creates XTEST handle} bin [binary!]]"
116+
"hob1: command [{creates XTEST handle} bin [binary!] /with hnd [handle!]]"
117117
"hob2: command [{prints XTEST handle's data} hndl [handle!]]"
118118
"str0: command [{return a constructed string}]"
119119
"echo: command [{return the input value} value]"
120120

121121
"init-words [id data length] protect/hide 'init-words\n"
122-
"a: b: c: h: x: none\n"
122+
"a: b: c: h: x: y: none\n"
123123
"i: make image! 2x2\n"
124124
"s: #[struct! [r [uint8!]]]\n"
125125
"xtest: does [\n"
@@ -129,6 +129,10 @@ char *RX_Spec =
129129
"[x/id: 2 print [{now the id is:} x/id]]\n"
130130
"[print [{It is not possible to change its length:} error? try [x/length: 3]]]\n"
131131
"[hob2 x]"
132+
133+
// Sometimes handle may depend on another handle.. this test simulates it.
134+
"[y: hob1/with #{00} x x: none print [{The new handle keeps reference to the second handle:} mold y/data y/data/2/id]]\n"
135+
132136
"[h: hndl1]\n"
133137
"[hndl2 h]\n"
134138
"[xarg0]\n"
@@ -356,7 +360,7 @@ RXIEXT int RX_Call(int cmd, RXIFRM *frm, void *ctx) {
356360
return RXR_UNSET;
357361
}
358362
break;
359-
case CMD_hob1: //command [{creates XTEST handle} bin [binary!]]"
363+
case CMD_hob1: //command [{creates XTEST handle} bin [binary!] /with hnd [handle!]]"
360364
{
361365
REBHOB *hob = RL_MAKE_HANDLE_CONTEXT(Handle_XTest);
362366
REBSER *bin = RXA_SERIES(frm, 1);
@@ -365,12 +369,20 @@ RXIEXT int RX_Call(int cmd, RXIFRM *frm, void *ctx) {
365369
if (SERIES_REST(bin) < 1) {
366370
RL_EXPAND_SERIES(bin, SERIES_TAIL(bin), 1);
367371
}
368-
hob->series = bin;
369372

370-
printf("data=> id: %u num: %i\n", data->id, data->num);
373+
if (RXA_REF(frm, 2)) {
374+
hob->series = RL_MAKE_BLOCK(2);
375+
data->flags = 1;
376+
RL_SET_VALUE(hob->series, 0, RXA_ARG(frm, 1), RXT_BINARY);
377+
RL_SET_VALUE(hob->series, 1, RXA_ARG(frm, 3), RXT_HANDLE);
378+
} else {
379+
hob->series = bin;
380+
data->flags = 0;
381+
}
382+
383+
printf("data=> id: %u flags: %i\n", data->id, data->flags);
371384
data->id = 1;
372-
data->num = SERIES_TAIL(bin);
373-
printf("data=> id: %u num: %i\n", data->id, data->num);
385+
printf("data=> id: %u flags: %i\n", data->id, data->flags);
374386

375387
RXA_HANDLE(frm, 1) = hob;
376388
RXA_HANDLE_TYPE(frm, 1) = hob->sym;
@@ -383,10 +395,20 @@ RXIEXT int RX_Call(int cmd, RXIFRM *frm, void *ctx) {
383395
REBHOB* hob = RXA_HANDLE(frm, 1);
384396
if (hob->sym == Handle_XTest) {
385397
XTEST* data = (XTEST*)hob->data;
386-
REBSER *bin = hob->series;
398+
REBSER *bin, *ser;
399+
REBCNT type;
400+
if (data->flags == 1) {
401+
type = RL_GET_VALUE(hob->series, 0, &RXA_ARG(frm, 2));
402+
if (type != RXT_BINARY) return RXR_FALSE;
403+
bin = RXA_SERIES(frm, 2);
404+
} else {
405+
bin = hob->series;
406+
}
407+
408+
387409
SERIES_DATA(bin)[0] = SERIES_DATA(bin)[0] + 1;
388-
printf("data=> id: %u num: %i b: %i\n", data->id, data->num, (u8)SERIES_DATA(bin)[0]);
389-
RXA_INT64(frm, 1) = data->num;
410+
printf("data=> id: %u flags: %i b: %i\n", data->id, data->flags, (u8)SERIES_DATA(bin)[0]);
411+
RXA_INT64(frm, 1) = SERIES_DATA(bin)[0];
390412
RXA_TYPE(frm, 1) = RXT_INTEGER;
391413
}
392414
else {
@@ -424,9 +446,9 @@ int XTestContext_release(void* ctx) {
424446
XTEST* data = (XTEST*)ctx;
425447
printf("Relasing XTest context handle: %p\n", data);
426448
// do some final cleaning off the context's content
427-
printf("data=> id: %u num: %i\n", data->id, data->num);
449+
printf("data=> id: %u num: %i\n", data->id, data->flags);
428450
CLEARS(data);
429-
printf("data=> id: %u num: %i\n", data->id, data->num);
451+
printf("data=> id: %u num: %i\n", data->id, data->flags);
430452
return 0;
431453
}
432454

@@ -442,11 +464,11 @@ int XTestContext_get_path(REBHOB *hob, REBCNT word, REBCNT *type, RXIARG *arg) {
442464
case W_DATA:
443465
arg->series = hob->series;
444466
arg->index = 0;
445-
*type = RXT_BINARY;
467+
*type = (xtest->flags == 1) ? RXT_BLOCK : RXT_BINARY;
446468
break;
447469
case W_LENGTH:
448470
*type = RXT_INTEGER;
449-
arg->int64 = xtest->num;
471+
arg->int64 = SERIES_TAIL(hob->series);
450472
break;
451473
default:
452474
return PE_BAD_SELECT;
@@ -467,7 +489,7 @@ int XTestContext_set_path(REBHOB *hob, REBCNT word, REBCNT *type, RXIARG *arg) {
467489
case W_DATA:
468490
if (*type != RXT_BINARY) return PE_BAD_SET_TYPE;
469491
hob->series = arg->series;
470-
xtest->num = SERIES_TAIL(hob->series);
492+
//xtest->num = SERIES_TAIL(hob->series);
471493
break;
472494
default:
473495
return PE_BAD_SET;

0 commit comments

Comments
 (0)