unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
From: Linas Vepstas <linasvepstas@gmail.com>
To: Neil Jerram <neil@ossau.uklinux.net>
Cc: guile-user@gnu.org, Peter Brett <peter@peter-b.co.uk>, geda-dev@seul.org
Subject: Re: Help needed debugging segfault with Guile 1.8.7
Date: Sun, 28 Nov 2010 11:21:30 -0600	[thread overview]
Message-ID: <AANLkTikAzGV1e21bZUFuqRrcQxVoi8aBDMwkZ2gpNHDZ@mail.gmail.com> (raw)
In-Reply-To: <8739ql38pe.fsf@ossau.uklinux.net>

[-- Attachment #1: Type: text/plain, Size: 2904 bytes --]

On 28 November 2010 05:38, Neil Jerram <neil@ossau.uklinux.net> wrote:

> Peter Brett <peter@peter-b.co.uk> writes:
>
>> Sure.  libgeda uses direct management of memory, and the structures used
>> in its document object model need to be explicitly deleted when finished
>> with.  I decided to use a Guile smob to represent these structures for
>> access from Scheme code, with the pointer to the actual structure in
>> SCM_SMOB_DATA and with the low nibble of SCM_SMOB_FLAGS indicating which
>> type of DOM structure the smob references.
>>
>> This would have been sufficient if Scheme code had only been working
>> with libgeda DOMs created and managed entirely via Scheme code. [...]
>
> I think your design is similar to what is outlined in the `Extending
> Dia' node of the Guile manual.  Were you aware of that doc before
> working out your design?  If not, I guess we need to make it more
> prominent.  If yes, I'd appreciate any suggestions you have for how it
> may be improved.

Yes, I code almost entirely 'by example', so having a good cookbook is
critical for me. I haven't read 'Extending Dia' before, its probably more
recent than the last time I set up guile bindings, some 2-3 years ago;
I skimmed it briefly just now.

Several comments on example code:
1) its typically not possible to wrap the C main(), so having a well-defined
init() that happens some time later would be best.

2) http://www.gnu.org/software/guile/manual/html_node/Dia-Hook.html
is lame.  What I have to do is this:

   SCM rc = scm_c_catch (SCM_BOOL_T,
                         (scm_t_catch_body) scm_c_eval_string,
                         (void *) expr_str,
                         SchemeEval::catch_handler_wrapper, this,
                         SchemeEval::preunwind_handler_wrapper, this);

and my catch_handler and preunwind_handler are fairly involved.

Basically, if you are going to let users enter arbitrary scheme into
your app, they *will* enter malformed, broken expressions, and you
have to deal with these.  Among other things, you have to give them
a clue as to what the error was -- some sort of trace, error reporting.

For me, this was implementing a REPL loop look-alike in my app.
I can't say "work-alike", I think mine *almost* works-alike, but not sure.

It took me a *long* time to figure out I needed the pre-unwind version
of things, and even then, it took me a fair amount of effort to figure
out what to put in there.

Having a section showing how to implement a repl-work-alike loop
in one's app, with reasonable debugging/stack-printing output,
would be nice to have.  Figuring out how to do this one one's
own requires a lot of tenacity.

For the record, I've attched the code I wrote to do the above (and
to multi-thread, which someone later on disabled :-( Its in C++,
sorry about that, don't blame me.)

--linas

[-- Attachment #2: SchemeEval.h --]
[-- Type: text/x-chdr, Size: 3283 bytes --]

/*
 * SchemeEval.h
 *
 * Simple scheme expression evaluator
 * Copyright (c) 2008 Linas Vepstas <linas@linas.org>
 */

#ifndef OPENCOG_SCHEME_EVAL_H
#define OPENCOG_SCHEME_EVAL_H
#ifdef HAVE_GUILE

#include <string>
#include <pthread.h>
#include <libguile.h>
#include <opencog/atomspace/Handle.h>

namespace opencog {

class SchemeEval
{
	private:
		// Initialization stuff
		void init(void);
		static void * c_wrap_init(void *);
		void per_thread_init(void);
		void thread_lock(void);
		void thread_unlock(void);
	
		// destructor stuff
		void finish(void);
		static void * c_wrap_finish(void *);
	
		// Things related to evaluation
		std::string do_eval(const std::string &);
		static void * c_wrap_eval(void *);
		static void * c_wrap_eval_h(void *);
		const std::string *pexpr;
		std::string answer;
		
		std::string input_line;
		bool pending_input;
	
		// straight-up evaluation
		static SCM wrap_scm_eval(void *);
		SCM do_scm_eval(SCM);
		SCM do_scm_eval_str(const std::string &);
	
		// Handle apply
		Handle do_apply(const std::string& func, Handle varargs);
		SCM do_apply_scm(const std::string& func, Handle varargs);
		Handle hargs;
		static void * c_wrap_apply(void *);
		static void * c_wrap_apply_scm(void *);
	
		// Error handling stuff
		SCM error_string_port;
		SCM captured_stack;
		static SCM preunwind_handler_wrapper(void *, SCM, SCM);
		static SCM catch_handler_wrapper(void *, SCM, SCM);
		SCM preunwind_handler(SCM, SCM);
		SCM catch_handler(SCM, SCM);
		bool caught_error;
	
		// printing of basic types
		static std::string prt(SCM);
	
		// output port
		SCM outport;
		SCM saved_outport;
	
		// Make constructor, destructor private; force
		// everyone to use the singleton instance, for now.
		SchemeEval(void);
		~SchemeEval();
		static SchemeEval* singletonInstance;
		
	public:
					
		std::string eval(const std::string &);
		Handle eval_h(const std::string &);
		Handle apply(const std::string& func, Handle varargs);
		std::string apply_generic(const std::string& func, Handle varargs);
	
		bool input_pending(void);
		void clear_pending(void);
		bool eval_error(void);
	
		// Someone thinks that there some scheme threading bug somewhere,
		// and the current hack around this is to use a singleton instance.
		static SchemeEval& instance(void)
		{
			if (!singletonInstance) 
				singletonInstance = new SchemeEval();
			return *singletonInstance;
		}
};

}

#else /* HAVE_GUILE */

#include <opencog/atomspace/Handle.h>

namespace opencog {

class SchemeEval
{
	private:
		static SchemeEval* singletonInstance;
	public:
		std::string eval(const std::string &s) { return ""; }
		Handle eval_h(const std::string &s) { return Handle::UNDEFINED; }
		Handle apply(const std::string &s, Handle args) {
			return Handle::UNDEFINED; }
		std::string apply_generic(const std::string& f, Handle args) {
			return ""; }
	
		bool input_pending(void) { return false; }
		void clear_pending(void) {}

		// If guile is not installed, then *every* call to eval_error()
		// must report that an error occurred! 
		bool eval_error(void) { return true; }

		static SchemeEval& instance(void)
		{
			if (!singletonInstance) 
				singletonInstance = new SchemeEval();
			return *singletonInstance;
		}
};

}
#endif/* HAVE_GUILE */
#endif /* OPENCOG_SCHEME_EVAL_H */

[-- Attachment #3: SchemeExec.cc --]
[-- Type: text/x-c++src, Size: 1934 bytes --]

/*
 * SchemeExec.cc
 *
 * Execute ExecutionLink's
 * Copyright (c) 2009 Linas Vepstas <linasvepstas@gmail.com>
 */

#ifdef HAVE_GUILE

#include <libguile.h>

#include <opencog/atomspace/Link.h>
#include <opencog/server/CogServer.h>

#include <boost/shared_ptr.hpp>

#include "SchemeEval.h"
#include "SchemeSmob.h"

using namespace opencog;

/**
 * do_apply -- apply named function func to arguments in ListLink
 * It is assumed that varargs is a ListLink, containing a list of
 * atom handles. This list is unpacked, and then the fuction func
 * is applied to them. If the function returns an atom handle, then
 * this is returned.
 */
Handle SchemeEval::do_apply(const std::string &func, Handle varargs)
{
	// Apply the function to the args
	SCM sresult = do_apply_scm (func, varargs);
	
	// If the result is a handle, return the handle.
	if (!SCM_SMOB_PREDICATE(SchemeSmob::cog_handle_tag, sresult))
	{
		return Handle::UNDEFINED;
	}
	return SchemeSmob::scm_to_handle(sresult);
}

/**
 * do_apply_scm -- apply named function func to arguments in ListLink
 * It is assumed that varargs is a ListLink, containing a list of
 * atom handles. This list is unpacked, and then the fuction func
 * is applied to them. The SCM value returned by the function is returned.
 */
SCM SchemeEval::do_apply_scm( const std::string& func, Handle varargs )
{
	SCM sfunc = scm_from_locale_symbol(func.c_str());
	SCM expr = SCM_EOL;
	
	// If there were args, pass the args to the function.
    boost::shared_ptr<Link> largs = cogserver().getAtomSpace()->cloneLink(varargs);
	if (largs)
	{
		const std::vector<Handle> &oset = largs->getOutgoingSet();
		
		size_t sz = oset.size();
		for (int i=sz-1; i>=0; i--)
		{
			Handle h = oset[i];
			SCM sh = SchemeSmob::handle_to_scm(h);
			expr = scm_cons(sh, expr);
		}
	}
	expr = scm_cons(sfunc, expr);
	return do_scm_eval(expr);
}

#endif
/* ===================== END OF FILE ============================ */

  reply	other threads:[~2010-11-28 17:21 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-11-10 12:43 Help needed debugging segfault with Guile 1.8.7 Peter TB Brett
2010-11-10 21:35 ` Peter TB Brett
2010-11-11 10:52   ` Peter Brett
2010-11-11 12:37     ` Thien-Thi Nguyen
2010-11-11 14:22       ` Peter Brett
2010-11-28 11:38         ` Neil Jerram
2010-11-28 17:21           ` Linas Vepstas [this message]
2010-11-30 19:56             ` Peter TB Brett
2010-12-01 19:48               ` Andy Wingo
2010-11-30 19:43           ` Peter TB Brett
2010-12-01 13:46             ` Ludovic Courtès
2010-12-03  7:52               ` Peter TB Brett
2010-11-11  8:22 ` rixed
2010-11-11  8:33 ` Neil Jerram
2010-11-11 13:30 ` Ludovic Courtès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=AANLkTikAzGV1e21bZUFuqRrcQxVoi8aBDMwkZ2gpNHDZ@mail.gmail.com \
    --to=linasvepstas@gmail.com \
    --cc=geda-dev@seul.org \
    --cc=guile-user@gnu.org \
    --cc=neil@ossau.uklinux.net \
    --cc=peter@peter-b.co.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).