Subject: bug#17893: 24.4.50; (error "Marker does not point anywhere")

From: [email-masked] (Charles A. Roelli)
Date: Fri, 24 Nov 2017 21:18:36 +0100

> Date: Mon, 20 Nov 2017 22:29:55 +0200
> From: Eli Zaretskii <[email-masked]>
> CC: [email-masked], [email-masked]
> Reply-to: Eli Zaretskii <[email-masked]>
> 
> > Date: Mon, 20 Nov 2017 21:01:58 +0100
> > From: [email-masked] (Charles A. Roelli)
> > CC: [email-masked], [email-masked]
> > 
> > > For mark-ring, I think it's easier to just reset it to nil in the new
> > > clone (it's arguably even more correct, since this is a fresh buffer),
> > > but in general this is a ticking bomb, unless I'm missing something.
> > > If I'm right, the only solution is to walk all the markers that point
> > > to the parent buffer and clone them to point to the cloned buffer
> > > (this has to be done in C).
> > 
> > By C, do you mean the function `clone-buffer'?
> 
> No, I meant what's in marker.c.

I suppose the main issue is fixed in master now:

> branch: master
> commit 197dd690112e8eef6457b16adbe6e2c1d801c849
> Date: Thu, 23 Nov 2017 13:33:34 -0500 (EST)
> Author: Stefan Monnier <[email-masked]>
> Commit: Stefan Monnier <[email-masked]>
>
>     * lisp/simple.el (clone-buffer): Adjust `mark-ring'
> ---
>  lisp/simple.el | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/lisp/simple.el b/lisp/simple.el
> index fde6669..41f22b2 100644
> --- a/lisp/simple.el
> +++ b/lisp/simple.el
> @@ -8516,13 +8516,16 @@ after it has been set up properly in other respects."
> 
>        ;; Set up other local variables.
>        (mapc (lambda (v)
> -	      (condition-case ()	;in case var is read-only
> +	      (condition-case ()
>  		  (if (symbolp v)
>  		      (makunbound v)
>  		    (set (make-local-variable (car v)) (cdr v)))
> -		(error nil)))
> +		(setting-constant nil))) ;E.g. for enable-multibyte-characters.
>  	    lvars)
> 
> +      (setq mark-ring (mapcar (lambda (mk) (copy-marker (marker-position mk)))
> +                              mark-ring))
> +
>        ;; Run any hooks (typically set up by the major mode
>        ;; for cloning to work properly).
>        (run-hooks 'clone-buffer-hook))

To solve the problem more generally, maybe clone-buffer could look for
local variables with a non-nil symbol property (called, say,
`clone-buffer-update-function'), the value of which would be a
function that updates the "cloned" variable properly.

So with mark-ring, you would do something like:

(put 'mark-ring 'clone-buffer-update-function
     (lambda (sym old-buf new-buf)
       (with-current-buffer new-buf
	 (set sym (with-current-buffer old-buf
		    (mapcar (lambda (mk) (copy-marker (marker-position mk)))
			    mark-ring))))))