multiprocessing with lisp, let* - multiprocessing

I am trying to create a process that uses a let*. When I try to run it, the child process is in a [reset] state. If I use a workaround and use let, the thread starts out as [active] everything works fine.
I am puzzled at this behavior and would love an explanation.
(defparameter *g* 1)
(defparameter *res-list* nil)
(defun tester ()
(let ((res *g*))
(push res *res-list*)))
CL-USER> (ccl:process-run-function "test" 'tester)
#<PROCESS test(4856) [Active] #x3020036E30AD>
CL-USER> *res-list*
(1)
Everything works so far. But if I change the let to let*, I get a [reset] state, but the code within the child thread is executed.
(defun tester ()
(let* ((res *g*))
(push res *res-list*)))
CL-USER> (ccl:process-run-function "test" 'tester)
#<PROCESS test(4862) [Reset] #x3020036BCF2D>
CL-USER> *res-list*
(1 1)
I would also be thankful if someone could point me to a resource which would explain the different states.
Thanks.

The different results are not because of let and let*. Processes can be in different states, and you're just seeing different results based on when you're catching the process to print it. When I run your code at the command line, I get mostly "Reset", but also some "Exhausted" and "Dead".
$ ccl64
Welcome to Clozure Common Lisp Version 1.7-r14925M (LinuxX8664)!
? (defparameter *g* 1)
*G*
? (defparameter *res-list* nil)
*RES-LIST*
? (defun tester ()
(let ((res *g*))
(push res *res-list*)))
TESTER
? (ccl:process-run-function "test" 'tester)
#<PROCESS test(2) [Exhausted] #x30200058FDBD>
? (ccl:process-run-function "test" 'tester)
#<PROCESS test(3) [Reset] #x30200058CB3D>
? (ccl:process-run-function "test" 'tester)
#<PROCESS test(4) [Reset] #x30200058AB3D>
? (ccl:process-run-function "test" 'tester)
#<PROCESS test(7) [Dead] #x302000584B3D>
? (ccl:process-run-function "test" 'tester)
#<PROCESS test(8) [Reset] #x302000582B3D>
The manual doesn't say a whole lot about these different states, as far as I can tell, but it does have this, which should be enough to get you digging into other parts of the manual:
7.3.2. As of August 2003:
It's not clear that exposing PROCESS-SUSPEND/PROCESS-RESUME is a good idea: it's not clear that they offer ways to win, and it's clear
that they offer ways to lose.
It has traditionally been possible to reset and enable a process that's "exhausted" . (As used here, the term "exhausted" means that
the process's initial function has run and returned and the underlying
native thread has been deallocated.) One of the principal uses of
PROCESS-RESET is to "recycle" threads; enabling an exhausted process
involves creating a new native thread (and stacks and synchronization
objects and ...),and this is the sort of overhead that such a
recycling scheme is seeking to avoid. It might be worth trying to
tighten things up and declare that it's an error to apply
PROCESS-ENABLE to an exhausted thread (and to make PROCESS-ENABLE
detect this error.)
When native threads that aren't created by Clozure CL first call into lisp, a "foreign process" is created, and that process is given
its own set of initial bindings and set up to look mostly like a
process that had been created by MAKE-PROCESS. The life cycle of a
foreign process is certainly different from that of a lisp-created
one: it doesn't make sense to reset/preset/enable a foreign process,
and attempts to perform these operations should be detected and
treated as errors.

Related

Call a procedure in Scheme after waiting a few seconds?

Is it possible to call a procedure in Scheme after waiting a few seconds?
For example:
(define (facs)
(fac 3)
;wait 5 seconds
(fac 7))
There is no provision for a sleep procedure in Standard Scheme; you will need to rely on implementation-specific features.
If you are using Guile Scheme, you can use sleep to sleep for a number of seconds, or usleep to sleep for a number of microseconds:
(define (delayed-5s msg)
(display "Waiting 5s...")
(force-output)
(sleep 5)
(newline)
(display msg)
(newline))
Note that you should flush the output to be sure that messages are seen when you want them seen. Typically, (but not always) printing a newline will flush the output buffer, so you could move (newline) before (sleep 5) and reasonably expect that the display will work as expected; but it is better to flush the output explicitly to ensure that messages are flushed from the output buffer when you want them to be. In the above code, both force-output and sleep are Guile-specific procedures.
If you are using Chez Scheme, you can do this:
(define (delayed-5s msg)
(display "Waiting 5s...")
(flush-output-port (current-output-port))
(sleep (make-time 'time-duration 0 5))
(newline)
(display msg)
(newline))
In Chez Scheme, sleep takes a time object, and make-time takes three arguments, returning a time object. The first of those is a time-type argument, the second is the number of nanoseconds, and the third is the number of seconds. Again, you should flush the output buffer, and flush-output-port does that, but it needs an output-port, which the procedure current-output-port provides. In the above code, sleep and make-time are Chez-specific procedures, but flush-output-port and current-output-port are standard R6RS Scheme library procedures.
You can see that using the sleep facility provided by Chez Scheme is a little bit more involved than the one provided by Guile Scheme. Other implementations are likely to have similar provisions, but they are not required to.
Not in portable Scheme as far as I know. Many implementations will have ways of doing this, of course. For instance in Racket:
(define (sleepy s)
(values (current-seconds)
(begin
(sleep s)
(current-seconds))))
> (sleepy 2)
1612809817
1612809819
(Of course, current-seconds is also not part of standard Scheme.)

Guarantee that flycheck-mode appears in first position in the mode line

When coding in not too wide buffer flycheck errors tally that should be visible in line-mode gets truncated. How do I guarantee that flycheck mode tally comes first in the order of major/minor modes in line-mode?
The minor modes are displayed in the order of minor-mode-alist. By default this simply reflects the load order (hence the kind-of-workaround you noted, but noting that the workaround would fail once additional minor modes were loaded).
Manipulating the list after libraries are loaded lets you maintain a desired display order on an ongoing basis.
(defun my-promote-flycheck (&optional _file)
"Give `flycheck-mode' priority position in `minor-mode-alist'.
Called via `after-load-functions', as well as `after-init-hook'."
(unless (eq (caar minor-mode-alist) 'flycheck-mode)
(let ((found (assq 'flycheck-mode minor-mode-alist)))
(when found
(assq-delete-all 'flycheck-mode minor-mode-alist)
(push found minor-mode-alist)))))
(add-hook 'after-load-functions 'my-promote-flycheck)
(add-hook 'after-init-hook 'my-promote-flycheck)

how to debug font lock keywords error

How can I debug font lock keywords I write? For example
(progn
(font-lock-add-keywords
nil
'(
;; ("hi1" . 'success)
("hi2" . (intern (concat "warn" "ing")))
))
(font-lock-fontify-buffer))
will produce the following message in Messages buffer:
Error during redisplay: (jit-lock-function 1) signaled (wrong-type-argument stringp 22)
In order to see the call stack upon wrong-type-argument error, I invoke toggle-debug-on-error and Emacs still doesn't enter debugger upon font lock error.
font-lock
can be applied in different ways. By default it is applied using
jit-lock-mode, which applies it "lazily" (aka "just-in-time"), which has
the disadvantage that it is applied at a time where we can't display
message (or enter the debugger) because that would make us inf-loop. So
there are two ways to work around the problem:
Use jit-lock-debug-mode (recently added to Emacs's development
code).
Set font-lock-support-mode to nil, then turn font-lock off and then
back on.
Both options should change font-lock so that it is applied at a time
where debugging can be used.

difference between continue and quit in Emacs Lisp debugger

(progn
(print 11)
(/ 1 0)
(print 22)
(/ 2 0)
(print 33))
When I press C-M-x on that expression, Emacs invokes debugger when it fails at (/ 1 0). When I press c for continue instead of q for quit, debugger still exits without executing (print 22) or (/ 2 0). The only difference here is that c exits with the message
progn: Arithmetic error
What is an example code where c and q make big difference and when should I type c rather than q?
The difference can be shown in any code that does not stop the execution, i.e. does not contain an error (for example, when called by debug).
The difference is easiest to see when you use debug-on-signal. With this setting, the debugger gets called when an error is signalled, even if that error is handled by an enclosing condition-case. In such a situation c will continue the normal execution (i.e. signal the error, which in turn causes the handler code to be run, which may then continue execution normally).
At first it seemed to me like a very obvious question,
but after trying to build an example, I actually had to look in the info.
So let me summarize what I've clarified for myself:
c in edebug is not the same as c in gdb.
This one just stops for one second at each breakpoint and eventually quits.
I don't see at the moment how it can be useful to anyone.
The equivalent is instead g: this one will continue until next breakpoint
and stop there.
Here's a code example:
(defun foo ()
(setq x (loop for i from 1 to 100
collecting (* i i)))
(setq y (nth 5 x))
(incf y))
(foo)
To edebug it:
Paste this code into *scratch*
Move point inside foo and C-u C-M-x (calls edebug-defun)
Move point to y in setq y and M-x edebug-set-breakpoint
Move point to the closing paren in (foo) and C-j
You're now in edebug. Here you could do step 3 with the shortcut b
instead of M-x ...
You'll find that proceeding with SPC is tedious, since it will
move though each statement of the loop each time.
But if you press g you'll skip past the whole loop, ending up
in the statement that you're supposedly interested in.
Another difference is with respect to recursive edit. For example, I could invoke query-replace and then enter recursive edit and then type (/ 1 0) and evaluate it to enter debugger. Now if I press q, we are back to top level and no longer running query-replace. But if I press c instead, I am still inside recursive edit.
Update another difference. While in debugger, c is bound to debugger-continue which is a wrapper around exit-recursive-edit
and q is bound to top-level. That means any difference known about exit-recursive-edit vs top-level applies. See Recursive Edit - Emacs Manual for difference.
Here's an example adapted from an example in Recursive Editing - Emacs Lisp Manual to test differences.
(defun simple-rec ()
(forward-word 1)
(message "111")
(debug)
(message "222")
(forward-word 1))

sbcl debugging cl-gtk2-gk if the backend thread hangs

Some sample, straight forward gtk2 within-main-loop
I'm currently trying to add code at key-press-event
If I make an error in the guy code, the gui thread will hang in the repl, I can still get the repl back but I didn't find a way to continue with gui development without restarting sbcl and reloading all the packages
(defun run ()
(within-main-loop
; match the controls that matter to vars
(let ((window (builder-get-object builder "window"))
;....
; on window close keep the gtk running. helps with debugging
(g-signal-connect search-field "key-press-event" (lambda (w) (declare (ignore w)) (format "~a" "danut")))
(g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (leave-gtk-main)))
(widget-show window)))))
The error I get when I run this function is :
debugger invoked on a SIMPLE-ERROR in thread #:
There is no applicable method for the generic function
#
when called with arguments
(NIL).
With enough work I can fix the error, but everytime I get something broken in the gui I can't make the backend thread to continue from where it hanged.
I tried all kinds of thread functions. list-all-treads will show:
(#<SB-THREAD:THREAD "cl-gtk2 main thread" RUNNING {CF48EF1}>
#<SB-THREAD:THREAD "initial thread" RUNNING {AA5F591}>)
This is all I tried until now:
(sb-thread:list-all-threads)
(sb-thread:interrupt-thread (first (sb-thread:list-all-threads)) #'leave-gtk-main)
(sb-thread:terminate-thread (first (sb-thread:list-all-threads)))
I just can't get it unstuck.
What's your normal workflow with cl-gtk2-gtk, how do you avoid this problem?
Use sb-thread:release-foreground to switch between threads waiting for input. See Threads in SBCL for an example session.

Resources