[Ecls-list] "socket crash bug" im Vim+ECL fixed
Larry Clapp
larry at theclapp.org
Sat Jun 17 23:15:14 UTC 2006
[ Note: Cross-posted to both the Slim-Vim list and the ECL devel list. ]
I fixed the "socket crash bug" in Vim+ECL, and I think I discovered
what caused it (in that order!).
The fix: Change vim:add-input-listener so that instead of evaling a
list, it funcalls a closure.
Changes:
if_ecl.lisp:
(defun add-input-listener (stream callback)
"Registers a callback to be invoked when data arrives to a stream"
(check-type stream stream)
(check-type callback function)
(setf (gethash stream callbacks) callback)
- (add-input-listener-int stream `(safe-eval '(cl:funcall ,callback) nil))
+ (add-input-listener-int stream callback)
t)
if_ecl.c:
static void listener_callback(int fd, void *data)
{
- safe_eval_form((cl_object)data, FALSE);
+ cl_funcall(1, (cl_object) data);
I didn't make this change to fix the bug; I only made it because I
didn't like that invoking the network callback went like this
vim
-> listener_callback
-> safe_eval_form
-> si_eval_with_env
-> SAFE-EVAL
-> SAFE-EVAL
-> the callback
and I wanted it more like
vim
-> listener_callback
-> the callback
So the patch changed the invocation sequence, which made the bug
either go away, or made it a lot rarer. I assumed that using
SAFE-EVAL somehow caused problems, and I wanted to know why, so I
added it back into the callback. It didn't fail. I added another.
It still didn't fail. Somewhere in there, I re-read Jim's recent post
and studied what I changed, and what I changed it from, and gradually
the light came on.
Jim's post, in part:
> The GC ECL uses is the Boehm GC, which (thankfully) doesn't move
> things around. You do have to be careful of storing pointers to
> gc-allocated memory in non gc-allocated memory, e.g. storing an
> ECL closure pointer in malloc'd memory, such things arn't detected
> by the mark and sweep and can lead to premature collection and
> horrible problems. This is why the callbacks are stored in a CL
> hash-table as well to stop them from disappearing. Of course I may
> have got this wrong and messed up really really badly, maybe it is
> worth turning the gc off temporarily just to see what happens.
Look closely at ADD-INPUT-LISTENER, above. Notice that Jim puts the
callback into a hash table (so some Lisp datastructure will have a
reference to it, so the GC won't collect it), and then wraps a list
around it and gives Vim a pointer to the list, which we later EVAL.
(Now see there? I've just about given it away! :) The *callback* is
in the hashtable, but the *list around it isn't*! And nothing else
references it, either! One GC later and it's game over.
Anyway, the patch (all two lines of it :) is at theclapp.org[1].
Happy hacking!
-- Larry
[1] http://theclapp.org/repos/vim70+async+ecl/
More information about the ecl-devel
mailing list