Re: Where is the backtrace?
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/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?
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?
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
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
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
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
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
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
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