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.
Related
My expectation would be for debug-on-error to trap most anomalous events and show me what went wrong. However, this is not the case with json.el which uses signal instead of error.
The documentation cautions against using debug-on-signal and my brief experimentation with it pretty much confirms this -- there are signals all over the place, so I would have to trap on just the json-* signals to get anything useful out of this. But I can't get even that to work.
I was about to submit a bug report for json.el but I feel that I may be missing something. Is there a good, established reason why json.el prefers signal over error?
Steps to repro:
(require 'json)
(setq debug-on-error t
debug-on-signal t) ; "json" ; '("json") ;; Still nothing
(json-read-from-string "")
Somewhat more realistically, you would have an actual, real-life problem when you pass the output from something to json-read (or one of its convenience wrappers json-read-from-string, json-read-file, json-read-object, etc) and it doesn't contain what you expect.
The result, even with debug-on-signal set to t, is the following text in the *Messages* buffer, and not much else:
with no indication as to the source of the error, or anything. (In real code with a similar problem, I was seeing if: End of file during parsing .)
In fact, the default value of debug-ignore-errors includes end-of-file so you have to remove that to be able to debug this particular problem.
(delete 'end-of-file debug-ignored-errors)
or perhaps more realistically
(let (debug-ignored-errors)
(json-something))
to temporarily override the value of debug-ignored-errors for the duration of the json-something call.
... and then you don't need debug-on-signal at all.
So my speculation that the use of signal instead of error causes the problematic behavior turned out to be false.
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.
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.
(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))
I needed to go through an XML file looking for certain tags whose contents were human-recognizable but not regex-recognizable and to work on those tags. I put together a keyboard macro that did the work I needed, then tried to use the following elisp to let me step through the file and just press y or n for each tag instead of going back and forth between movement commands and macro executions.
(while t
(progn
(search-forward "<Name>")
(move-beginning-of-line nil)
(if (y-or-n-p "Problem? ")
(call-last-kbd-macro)
(next-line)
)))
However, when I M-: evaluated this, it got to y-or-n-p and then emacs became unresponsive. I am using emacs on an OS X 10.7 machine. In Activity Monitor, emacs was taking up the normal amount of RAM and CPU time, not making escalating resource requests, so I don't think I ran into an infinite loop. Emacs simply stopped responding to typing and clicks altogether, including things like repeatedly hitting Escape or C-g. An additional detail: the one y-or-n-p interaction I got was a dialog box, not in the minibuffer, which was strange - I clicked Yes on it and the dialog box went away, which was the last interaction I was able to get with emacs before it disappeared into deep space.
Is there something in the above elisp code that's inherently dangerous? My thought was that the (search-forward) would fail at the end of the buffer, signal an error, and the loop would end.
Try this so that the search fails the loop terminates. This code could still loop forever if the call-last-kbd-macro moves point back before the previous search.
(while (search-forward "<Name>" nil t)
(progn
(move-beginning-of-line nil)
(if (y-or-n-p "Problem? ")
(call-last-kbd-macro)
(next-line))))