Commit a416e1d6 authored by Eli Zaretskii's avatar Eli Zaretskii
Browse files

Fix point motion in cloned buffers

* src/thread.c (post_acquire_global_lock): Call
set_buffer_internal_2 instead of tricking set_buffer_internal_1
into resetting the current buffer even if it didn't change.  This
avoids bug#25165, caused by failing to record the modified values
of point and mark, because current_buffer was set to NULL.  Also,
don't bother re-setting the buffer if there was no thread switch,
as that just wastes cycles.
* src/buffer.c (set_buffer_internal_2): New function, with most of
the body of set_buffer_internal_1, but without the test for B
being identical to the current buffer.
(set_buffer_internal_1): Call set_buffer_internal_2 if B is not
identical to the current buffer.
* src/buffer.h (set_buffer_internal_2): Add prototype.

* test/src/thread-tests.el (thread-sticky-point): New test.
parent 00d4ba27
......@@ -2033,9 +2033,6 @@ DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0,
void
set_buffer_internal_1 (register struct buffer *b)
{
register struct buffer *old_buf;
register Lisp_Object tail;
#ifdef USE_MMAP_FOR_BUFFERS
if (b->text->beg == NULL)
enlarge_buffer_text (b, 0);
......@@ -2044,6 +2041,17 @@ set_buffer_internal_1 (register struct buffer *b)
if (current_buffer == b)
return;
set_buffer_internal_2 (b);
}
/* Like set_buffer_internal_1, but doesn't check whether B is already
the current buffer. Called upon switch of the current thread, see
post_acquire_global_lock. */
void set_buffer_internal_2 (register struct buffer *b)
{
register struct buffer *old_buf;
register Lisp_Object tail;
BUFFER_CHECK_INDIRECTION (b);
old_buf = current_buffer;
......
......@@ -1082,6 +1082,7 @@ extern void recenter_overlay_lists (struct buffer *, ptrdiff_t);
extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char **);
extern void validate_region (Lisp_Object *, Lisp_Object *);
extern void set_buffer_internal_1 (struct buffer *);
extern void set_buffer_internal_2 (struct buffer *);
extern void set_buffer_temp (struct buffer *);
extern Lisp_Object buffer_local_value (Lisp_Object, Lisp_Object);
extern void record_buffer (Lisp_Object);
......
......@@ -55,7 +55,6 @@ release_global_lock (void)
static void
post_acquire_global_lock (struct thread_state *self)
{
Lisp_Object buffer;
struct thread_state *prev_thread = current_thread;
/* Do this early on, so that code below could signal errors (e.g.,
......@@ -71,12 +70,12 @@ post_acquire_global_lock (struct thread_state *self)
if (prev_thread != NULL)
unbind_for_thread_switch (prev_thread);
rebind_for_thread_switch ();
}
/* We need special handling to re-set the buffer. */
XSETBUFFER (buffer, self->m_current_buffer);
self->m_current_buffer = 0;
set_buffer_internal (XBUFFER (buffer));
/* Set the new thread's current buffer. This needs to be done
even if it is the same buffer as that of the previous thread,
because of thread-local bindings. */
set_buffer_internal_2 (current_buffer);
}
if (!NILP (current_thread->error_symbol))
{
......
......@@ -221,8 +221,18 @@
:group 'widget-faces))
(ert-deftest thread-errors ()
"Test what happens when a thread signals an error."
"Test what happens when a thread signals an error."
(should (threadp (make-thread #'call-error "call-error")))
(should (threadp (make-thread #'thread-custom "thread-custom"))))
(ert-deftest thread-sticky-point ()
"Test bug #25165 with point movement in cloned buffer."
(with-temp-buffer
(insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
(goto-char (point-min))
(clone-indirect-buffer nil nil)
(forward-char 20)
(sit-for 1)
(should (= (point) 21))))
;;; threads.el ends here
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment