Returning a Rebol void value

When I created the MySQL extension, the way to return a void value from a function was to do a simple

return rebVoid();

Now I am dealing with the GTK3 extension and I suspect something about this has changed. Multiple occasions where I return a void like this appear to be resulting in a segfault and quitting the console as a result as well.

Was this method indeed changed? Or could it be that it is just unintentionally broken?

Should the

return rebVoid();

be replaced by

return Init_Void(D_OUT, SYM_VOID);

now?

grep -r "rebVoid()" .
./extensions/stdio/readline-posix.c:            return rebVoid();  // signal a HALT
./extensions/stdio/readline-posix.c:                    return rebVoid();  // signal a HALT
./extensions/stdio/readline-windows.c:            return rebVoid();  // signal a HALT
./extensions/stdio/p-stdio.c:            line = rebVoid();
./extensions/stdio/p-stdio.c:                return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/viewgtk3/mod-viewgtk3.c:    return rebVoid();
./extensions/crypt/mod-crypt.c:    return rebVoid();
./extensions/crypt/mod-crypt.c:        return rebVoid();
./extensions/crypt/mod-crypt.c:        return rebVoid();
./extensions/odbc/mod-odbc.c:    return rebVoid();
./extensions/mysql/mod-mysql.c:        return rebVoid();
./extensions/mysql/mod-mysql.c:        return rebVoid();
./extensions/mysql/mod-mysql.c:    return rebVoid();
./extensions/mysql/mod-mysql.c:        return rebVoid(); 
./extensions/mysql/mod-mysql.c:    return rebVoid();
./src/core/a-lib.c:        result = rebVoid();
./src/core/t-bitset.c:            action = rebVoid();

grep -r "Init_Void(" .
./extensions/process/mod-process.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/process/mod-process.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/event/mod-event.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/event/mod-event.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/event/p-event.c:        return Init_Void(D_OUT, SYM_VOID);
./extensions/gob/mod-gob.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/gob/mod-gob.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/network/mod-network.c:        return Init_Void(D_OUT, SYM_VOID); }
./extensions/network/mod-network.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/stdio/mod-stdio.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/stdio/mod-stdio.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/signal/mod-signal.c:        return Init_Void(D_OUT, SYM_VOID); }
./extensions/crypt/mod-crypt.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/library/mod-library.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/library/mod-library.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/vector/mod-vector.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/vector/mod-vector.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/debugger/mod-debugger.c:        Init_Void(out, SYM_VOID);
./extensions/image/mod-image.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/image/mod-image.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/javascript/mod-javascript.c:        return Init_Void(D_OUT, SYM_VOID);
./extensions/javascript/mod-javascript.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/javascript/mod-javascript.c:    return Init_Void(D_OUT, SYM_VOID);
./extensions/dns/mod-dns.c:        return Init_Void(D_OUT, SYM_VOID);
./src/boot/words.r:; more communicative.  These are standard symbols passed to Init_Void().
./src/include/datatypes/sys-void.h:#define Init_Void(out,sym) \
./src/core/t-typeset.c:                Init_Void(DS_PUSH(), SYM_CUSTOM_X);
./src/core/d-test.c:    return Init_Void(D_OUT, SYM_VOID);
./src/core/d-test.c:    return Init_Void(D_OUT, SYM_VOID);
./src/core/l-scan.c:                Init_Void(DS_PUSH(), SYM_VOID);
./src/core/t-string.c:            return Init_Void(D_OUT, SYM_VOID);
./src/core/c-bind.c:    Init_Void(ARR_SINGLE(patch), SYM_UNSET);  // start variable off as unset
./src/core/c-bind.c:    return Init_Void(D_OUT, REB_VOID);
./src/core/c-bind.c:            Init_Void(var, SYM_VOID);
./src/core/functionals/c-augment.c:    Init_Void(DS_PUSH(), SYM_VOID);  // key slot (signal for no pushes)
./src/core/functionals/c-specialize.c:            Init_Void(arg, SYM_UNSET);  // *not* VAR_MARKED_HIDDEN
./src/core/functionals/n-function.c:    return Init_Void(f->out, SYM_VOID);
./src/core/functionals/n-function.c:    return Init_Void(f->out, SYM_VOID);
./src/core/functionals/n-function.c:        Init_Void(ARG(result), SYM_VOID);
./src/core/functionals/n-function.c:            Init_Void(v, SYM_VOID); // `do [return]` acts as `return void`
./src/core/functionals/c-lambda.c:    Init_Void(DS_PUSH(), SYM_VOID);  // key slot (signal for no pushes)
./src/core/functionals/c-hijack.c:        out,  // invisibles allow for out to not be Init_Void()'d
./src/core/functionals/c-generic.c:    return Init_Void(D_OUT, SYM_VOID);
./src/core/functionals/c-chain.c:    Init_Void(FRM_SPARE(f), SYM_UNSET);
./src/core/functionals/c-native.c:    // `return: <void>` use `return: [void!]` and `return Init_Void(D_OUT);`
./src/core/c-context.c:    REBVAL *value = Init_Void(ARR_LAST(CTX_VARLIST(context)), SYM_UNSET);
./src/core/c-context.c:                    Init_Void(var, SYM_UNSET);  // not in source context
./src/core/n-control.c:        return Init_Void(D_OUT, SYM_MATCHED);
./src/core/c-function.c:            Init_Void(param, SYM_UNSET);
./src/core/c-function.c:    Init_Void(KEY_SLOT(DSP), SYM_VOID);  // signal for no parameters pushed
./src/core/b-init.c:    Init_Void(Prep_Cell(&PG_Unset_Value), SYM_UNSET);  // symbol never GC'd
./src/core/t-binary.c:            return Init_Void(D_OUT, SYM_VOID);
./src/core/a-lib.c:    return Init_Void(Alloc_Value(), SYM_VOID);
./src/core/n-do.c:        Init_Void(D_OUT, SYM_VOID);
./src/core/t-datatype.c:            Init_Void(value, SYM_VOID);
./src/core/t-datatype.c:            Init_Void(value, SYM_VOID);
./src/core/n-loop.c:                Init_Void(les->out, SYM_NULLED);  // null signals break only
./src/core/f-series.c:                return Init_Void(D_OUT, SYM_VOID);  // !!! better than error?
./src/core/n-system.c:        Init_Void(ARG(value), SYM_QUIT);
./src/core/n-data.c:            Init_Void(dest, SYM_NULLED);  // blocks can't contain nulls
./src/core/n-data.c:        return Init_Void(D_OUT, SYM_NULLED);
./src/core/n-data.c:    return Init_Void(D_OUT, SYM_VOID); // !!! Could return freed value
./src/core/n-data.c:        return Init_Void(D_OUT, SYM_NULLED);
./src/core/n-io.c:    return Init_Void(D_OUT, SYM_VOID);
./src/core/d-stats.c:    return Init_Void(D_OUT, SYM_VOID);
./src/core/m-pools.c:    return Init_Void(D_OUT, SYM_VOID);
./src/core/t-object.c:            Init_Void(var, SYM_VOID);
./src/core/c-error.c:                    Init_Void(var, SYM_END);
./src/core/c-error.c:                    Init_Void(var, SYM_VOID);
./src/core/u-parse.c:    Init_Void(Prep_Cell(ARG(num_quotes)), SYM_UNSET);
./src/core/u-parse.c:    Init_Void(Prep_Cell(ARG(position)), SYM_UNSET);
./src/core/u-parse.c:    Init_Void(Prep_Cell(ARG(save)), SYM_UNSET);
./src/core/u-parse.c:            Init_Void(D_SPARE, SYM_VOID);

I replaced my return rebVoid(); 's with the return Init_Void 's
Alas, this did not resolve the segfault when closing the window.

I take it that both methods to return a void are actual and functional.

So....

It appears I resolved the segfault issue now!

Of course it was my own stupid mistake(*), not connecting the right information in the signal-connect function.

I can now exit the window and return to a working console again.

Next step up is get a Rebol function to act as a valid callback function. (**)

(*) The stupid mistake only to be taking up this work :smile:
(**) Check for the latest update on this the ever growing GTK3 GUI thread ( Just moving ahead now with GTK3 - #17 by iArnold )

Sounds like you got it working, but the first API (the rebXXX() routines) are what are supposed to be the public API routines... the ones most people use.

Think of this as the "libRenC", it would be analogous to what Red calls "libRed".

The other API (D_OUT, SYM_XXX, Init_XXX) is not something you should need to concern yourself with. That's internal to the implementation. It is currently exposed to institutions to be able to make a choice which to use, but the correct choice for 99% of the people is the rebXXX routines.

If you have a reproducible crash with the voids that is probably something that should not happen so please report what you were doing that made it crash. That's useful feedback.

But also interesting is if you're able to get things done, which indicates that the API design is making sense to you. Feedback there is important.

1 Like

Thanks @hostilefork .
Yes I can safely re-place the rebVoid()'s.
I got to doubt because I did not see many rebVoid()'s in the rest of the code base, only a few which might have been missed or not in active used code. And there is often a lot of philosophy going about how to handle NULL, None, Void, Blank resulting in perhaps a slight different approach and I could easily have missed something. But this is not the case here.

It would be a nice to have to get the API docs available