[plt-scheme] capturing output from different threads

From: Dave Griffiths (dave at pawfal.org)
Date: Thu Mar 6 16:17:50 EST 2008

On Wed, 2008-03-05 at 06:57 -0700, Matthew Flatt wrote:
> At Wed, 5 Mar 2008 10:53:33 -0000 (GMT), "Dave Griffiths" wrote:
> > I've been capturing the output from an embedded interpreter like so:
> > 
> > outport = scheme_make_byte_string_output_port();
> > errport = scheme_make_byte_string_output_port();
> > scheme_set_param(scheme_current_config(), MZCONFIG_OUTPUT_PORT, outport);
> > scheme_set_param(scheme_current_config(), MZCONFIG_ERROR_PORT, errport);
> > 
> > ...
> > scheme_eval_string_all(...)
> > ...
> > 
> > outmsg=scheme_get_sized_byte_string_output(outport,&size);
> > errmsg=scheme_get_sized_byte_string_output(errport,&size);
> > 
> > But this seems to crash the garbage collector elsewhere when I spawn a plt
> > thread in my script. Reading the docs it seems that scheme_set_param only
> > works for one thread, so I can imagine it would only work for the main
> > thread, so 1) is there a way to get new threads to inherit the main
> > thread's parameters and 2) will it also make the garbage collector happy?
> > ;)
> 
> As Chongkai says, this should work the way you want: the parameters are
> inherited by threads created during the scheme_eval_string_all() call.
> 
> Are all the threads created and run in the "..." above? If so, I don't
> have an idea at the moment for what might be wrong; maybe a stack trace
> would help.

Ok - I've got some minimal code which crashes on my setup (ubuntu/plt
3.72). I think I'm marking everything correctly for the garbage
collector, but I'm never totally sure :)

--->8---

#define MZ_PRECISE_GC
#include <scheme.h>

Scheme_Object *outport=NULL;
Scheme_Object *errport=NULL;

void interpret(Scheme_Env *e, char *code)
{
	mz_jmp_buf * volatile save=NULL, fresh;
	char *msg=NULL;
	
   	MZ_GC_DECL_REG(5);
    	MZ_GC_VAR_IN_REG(0, outport);
    	MZ_GC_VAR_IN_REG(1, errport);
    	MZ_GC_VAR_IN_REG(2, e);
    	MZ_GC_VAR_IN_REG(3, msg);
	MZ_GC_VAR_IN_REG(4, save);
    	MZ_GC_REG();
	
	save = scheme_current_thread->error_buf;
    	scheme_current_thread->error_buf = &fresh;
	
    	if (scheme_setjmp(scheme_error_buf)) 
	{
		scheme_current_thread->error_buf = save;
		exit(-1);
    	} 
	else 
	{
		scheme_eval_string_all(code, e, 1);
    	}	
	scheme_current_thread->error_buf = save;
			
	long size=0;
	msg=scheme_get_sized_byte_string_output(outport,&size);
	if (size>0) printf("%s\n",msg);
	msg=scheme_get_sized_byte_string_output(errport,&size);
	if (size>0) printf("%s\n",msg);
	
	MZ_GC_UNREG();
}

int main(int argc, char *argv[])
{
	void *stack_start;
	stack_start = (void *)&stack_start;
	Scheme_Env *e = NULL;
	Scheme_Config *config = NULL;

	MZ_GC_DECL_REG(4);
	MZ_GC_VAR_IN_REG(0, e);
	MZ_GC_VAR_IN_REG(1, outport);
	MZ_GC_VAR_IN_REG(2, errport);
	MZ_GC_VAR_IN_REG(3, config);
	scheme_set_stack_base( &__gc_var_stack__, 1);
 	MZ_GC_REG();
	e = scheme_basic_env();

	outport = scheme_make_byte_string_output_port();
	errport = scheme_make_byte_string_output_port();
	config = scheme_current_config();
	scheme_set_param(config, MZCONFIG_OUTPUT_PORT, outport);
	scheme_set_param(config, MZCONFIG_ERROR_PORT, errport);
	
	interpret(e,"\
		(define (go) \
			(define (loop n)\
				(printf \"hello~n\")\
				(loop (+ n 1))) \
			(display \"going...\")(newline)\
			(loop 0))\
        (thread go)");

	while(1)
	{
		interpret(e,"");
	}
	
	MZ_GC_UNREG();
		
	return 0;
}

And the stack trace is:

Seg fault (internal error) at 0x91288

Program received signal SIGABRT, Aborted.
0xffffe410 in __kernel_vsyscall ()
(gdb) bt
#0  0xffffe410 in __kernel_vsyscall ()
#1  0xb7a74df0 in raise () from /lib/tls/i686/cmov/libc.so.6
#2  0xb7a76641 in abort () from /lib/tls/i686/cmov/libc.so.6
#3  0xb7e26015 in fault_handler (sn=11, si=0xbf90049c, ctx=0xbf90051c)
    at ./sighand.c:20
#4  <signal handler called>
#5  0xb7e2a2b7 in GC_mark_variable_stack (var_stack=0xbf900d34, 
    delta=-133925852, limit=0xb7948e9c, stack_mem=0xb79480fc)
    at ./var_stack.c:73
#6  0xb7e1b315 in MARK_jmpup (buf=0xb78180b4) at xsrc/type.c:306
#7  0xb7e1b43d in thread_val_MARK (p=0xb7818020) at xsrc/type.c:1175
#8  0xb7e29fcd in propagate_marks () at ./newgc.c:2222
#9  0xb7e27726 in garbage_collect (force_full=<value optimized out>)
    at ./newgc.c:2924
#10 0xb7e2b14d in allocate_big (sizeb=1638436, type=1) at ./newgc.c:399
#11 0xb7d900af in string_write_bytes (port=0xb7792500, 
    str=0xbf900ae4 "hello\n\220�\024\v\220�\f\v\220�", d=0, len=5, 
    rarely_block=0, enable_break=0) at xsrc/portfun.c:682
#12 0xb7d86873 in scheme_put_byte_string (who=0xb7e414d7 "printf", 
    port=0xb7792500, str=0xbf900ae4 "hello\n\220�\024\v\220�\f\v\220�",
d=0, 
    len=5, rarely_block=0) at xsrc/port.c:3135
#13 0xb7d86c41 in scheme_put_char_string (who=0xb7e414d7 "printf", 
    port=0xb7792500, str=0xb779d0b4, d=0, len=5) at xsrc/port.c:3205




Posted on the users mailing list.