Re: Where is the backtrace?

2014-01-03 Thread Ian Price
Panicz Maciej Godek  writes:

>> (define (f) (define (g) (define (h) ((lambda x (cdr x (h)) (g))
>> (f)
> :13:0: In procedure # input>:13:0 x>:
> :13:0: In procedure cdr: Wrong type argument in position
> 1 (expecting pair): ()
>
> Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue
>
>> ,bt
> In current input:
>  13:0  0 (#:13:0 x>)
>
> Why isn't the information about the subsequent procedures tracked? Do
> they all get inlined?

scheme@(guile-user)> ,optimize (define (f) (define (g) (define (h) ((lambda x 
(cdr x (h)) (g))
$2 = (define (f) (cdr '()))

So, yes.

Though not relevant to this case, there is also another important factor
in your code, which is that all function calls are tail calls. So even
if you turned off optimisation, you would not see a complete backtrace.

-- 
Ian Price -- shift-reset.com

"Programming is like pinball. The reward for doing it well is
the opportunity to do it again" - from "The Wizardy Compiled"



Re: Where is the backtrace?

2014-01-03 Thread Panicz Maciej Godek
2014/1/3 Ian Price :
[...]
>> Why isn't the information about the subsequent procedures tracked? Do
>> they all get inlined?
>
> scheme@(guile-user)> ,optimize (define (f) (define (g) (define (h) ((lambda x 
> (cdr x (h)) (g))
> $2 = (define (f) (cdr '()))
>
> So, yes.
>
> Though not relevant to this case, there is also another important factor
> in your code, which is that all function calls are tail calls. So even
> if you turned off optimisation, you would not see a complete backtrace.

I've checked this with other implementations. Racket, Gambit and Biwa
Scheme were equally uninformative. Kawa's backtrace was a nightmare to
me, but perhaps someone with more knowledge would be able to infer the
actual location of the error. Actually, the only implementation that
exposed the exact location was Chicken. It proves that there must be a
way to track this information in spite of TCO.



Re: Where is the backtrace?

2014-01-03 Thread Ian Price
Panicz Maciej Godek  writes:

> I've checked this with other implementations. Racket, Gambit and Biwa
> Scheme were equally uninformative. Kawa's backtrace was a nightmare to
> me, but perhaps someone with more knowledge would be able to infer the
> actual location of the error. Actually, the only implementation that
> exposed the exact location was Chicken. It proves that there must be a
> way to track this information in spite of TCO.
>
It depends on just how much information you want to keep
around. Obviously, most of us don't want a full stack trace for a (let
loop () (if ... (loop))). There would simply be no (legible) way in
Scheme to write an infinite loop without proper tail recursion.

I'm not about to argue either side of this, but I will note that I added
a wishlist item for improving backtraces to the tracker a while back,
and it's free for anyone who wants to, to hack on.

See http://debbugs.gnu.org/cgi/bugreport.cgi?bug=11215.

(As for Racket, I suspect you would get better info in the gui than the
console version.)

-- 
Ian Price -- shift-reset.com

"Programming is like pinball. The reward for doing it well is
the opportunity to do it again" - from "The Wizardy Compiled"



Re: Where is the backtrace?

2014-01-03 Thread Mark H Weaver
Panicz Maciej Godek  writes:

> I've checked this with other implementations. Racket, Gambit and Biwa
> Scheme were equally uninformative. Kawa's backtrace was a nightmare to
> me, but perhaps someone with more knowledge would be able to infer the
> actual location of the error. Actually, the only implementation that
> exposed the exact location was Chicken. It proves that there must be a
> way to track this information in spite of TCO.

I suspect the reason Chicken kept the information is that in Chicken,
IIUC, tail calls are just normal C function calls, so the stack fills
until it reaches a certain size and then is garbage collected.

The solution I favor is that of MIT Scheme, which records the backtrace
as a chain of rings.  Each time a tail call is done, an entry is
recorded in the topmost ring, so between every two non-tail calls, up to
N tail calls are preserved.  If more than N tail calls are done in a
row, then the older ones are forgotten.

Hopefully we'll have this for Guile some day.

 Mark



libguile thread safety

2014-01-03 Thread Chris Vine
Hi,

I am having problems using libguile in a multi-threaded environment,
which boils down to the following small test case, which fails with a
segmentation fault with guile-2.0.9:

#include 
#include 

void *guile_wrapper (void *data) {
  scm_c_eval_string ("(display \"Hello\n\")");
  return NULL;
}

void *thread_func (void *data) {
  scm_with_guile (&guile_wrapper, NULL);
  return NULL;
}

int main () {
  pthread_t thread1;
  pthread_t thread2;

  pthread_create (&thread1, NULL, thread_func, NULL);
  pthread_create (&thread2, NULL, thread_func, NULL);

  pthread_join (thread1, NULL);
  pthread_join (thread2, NULL);
  return 0;
}

However, it prints "Hello" correctly if only one thread is started.
It seems that scm_with_guile() is not thread safe in the form used
above. However the following suggest that it should be:

http://www.gnu.org/software/guile/manual/html_node/Multi_002dThreading.html#Multi_002dThreading
http://www.gnu.org/software/guile/manual/html_node/Initialization.html#Initialization

I am clearly doing something wrong, which is probably obvious to
others. Can anyone help me with this?  Perhaps I have to serialize use
of scm_with_guile() notwithstanding what is said in the documentation,
but if so it will be disappointing for the use to which I was hoping to
put it.

Chris



Re: libguile thread safety

2014-01-03 Thread Panicz Maciej Godek
Hi,
I have never used the pthread library directly, but would it be
possible for your program to use scm_spawn_thread instead? (according
to the manual, it starts a new thread in guile mode, but I guess it
needs to be run in guile mode as well)



Re: libguile thread safety

2014-01-03 Thread Chris Vine
On Sat, 4 Jan 2014 01:08:12 +0100
Panicz Maciej Godek  wrote:
> Hi,
> I have never used the pthread library directly, but would it be
> possible for your program to use scm_spawn_thread instead? (according
> to the manual, it starts a new thread in guile mode, but I guess it
> needs to be run in guile mode as well)

That wouldn't help in my usage case I am afraid.  Essentially I am
trying to integrate some scheme code with some C++ code, which involves
running callable objects (tasks) on a thread pool.  Some will be native
C++ lambdas or other function objects, and some will be scheme code I
was intending to run on the guile VM. That seemed a natural fit for
libguile, but I was getting intermittent crashes when two tasks
involving scheme code on the VM tried to start at approximately the same
time.

I was hoping there was something obvious in the test case that I was
doing wrong. On the other hand, if it is a guile bug then I will have
to see if I can work around it.  If I can't, I may have to abandon this
aspect of the project and go C++ only.  If I have to serialize all
running of scheme code on libguile it would slow other stuff down too
much.

I am still hopeful someone will tell me I have got something wrong in
the test case.

Chris



Re: libguile thread safety

2014-01-03 Thread Panicz Maciej Godek
The code looks fine to me. It seems that there's a bug in guile --
when I insert one second sleep between the two invocations of
pthread_create, everything works fine. However, when I go down with
the sleep time below ~5 microseconds, things are getting weird.

The good news is that the problem appears only between the first and
the second invocation, but if you wait after creation of the first
thread, then everything seems OK.



Re: libguile thread safety

2014-01-03 Thread Panicz Maciej Godek
I concluded that this might be a solution. I tested it with 2.0.5 from
ubuntu repository. I had to add GC_allow_register_threads (and link
against gc, accordingly), because otherwise the program aborted with
the message "Threads explicit registering is not previously enabled"
whenever it attempted to create a thread.

For some reason the initialization routine needs to call
scm_c_eval_string; otherwise it doesn't help.

The solution doesn't fill me with joy, but I hope it works for you

#include 
#include 

void *guile_wrapper (void *data) {
  scm_c_eval_string ("(display \"Hello\n\")");
  return NULL;
}

void *thread_func (void *data) {
  scm_with_guile (&guile_wrapper, NULL);
  return NULL;
}

void *do_nothing(void *unused) {
  scm_c_eval_string("(noop)");
  return NULL;
}

int main () {
  pthread_t thread1;
  pthread_t thread2;

  GC_allow_register_threads();

  scm_with_guile(do_nothing, NULL);

  pthread_create (&thread1, NULL, thread_func, NULL);
  pthread_create (&thread2, NULL, thread_func, NULL);

  pthread_join (thread1, NULL);
  pthread_join (thread2, NULL);

  return 0;
}



Re: libguile thread safety

2014-01-03 Thread Mark H Weaver
Chris Vine  writes:
> I am having problems using libguile in a multi-threaded environment,
> which boils down to the following small test case, which fails with a
> segmentation fault with guile-2.0.9:

I've recently noticed that the module loading process in Guile is not
thread safe.  I hope to fix this in the next month or two, but for now
I'd recommend that one thread should initialize Guile and load the
modules that will be needed, before allowing multiple threads to enter
Guile mode.

Regards,
  Mark