diff options
| author | Eli Zaretskii | 2016-12-12 18:03:40 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2016-12-12 18:03:40 +0200 |
| commit | a416e1d6c111527205f3583c8d201bf95af6fa20 (patch) | |
| tree | 60e58859632f072952f84dee959eb0a88f3c097a /src | |
| parent | 00d4ba2794243763b818c013669e36c1d2c7de62 (diff) | |
| download | emacs-a416e1d6c111527205f3583c8d201bf95af6fa20.tar.gz emacs-a416e1d6c111527205f3583c8d201bf95af6fa20.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/buffer.c | 14 | ||||
| -rw-r--r-- | src/buffer.h | 1 | ||||
| -rw-r--r-- | src/thread.c | 11 |
3 files changed, 17 insertions, 9 deletions
diff --git a/src/buffer.c b/src/buffer.c index cea1ddb5ab3..babfba3e65f 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -2033,9 +2033,6 @@ DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0, | |||
| 2033 | void | 2033 | void |
| 2034 | set_buffer_internal_1 (register struct buffer *b) | 2034 | set_buffer_internal_1 (register struct buffer *b) |
| 2035 | { | 2035 | { |
| 2036 | register struct buffer *old_buf; | ||
| 2037 | register Lisp_Object tail; | ||
| 2038 | |||
| 2039 | #ifdef USE_MMAP_FOR_BUFFERS | 2036 | #ifdef USE_MMAP_FOR_BUFFERS |
| 2040 | if (b->text->beg == NULL) | 2037 | if (b->text->beg == NULL) |
| 2041 | enlarge_buffer_text (b, 0); | 2038 | enlarge_buffer_text (b, 0); |
| @@ -2044,6 +2041,17 @@ set_buffer_internal_1 (register struct buffer *b) | |||
| 2044 | if (current_buffer == b) | 2041 | if (current_buffer == b) |
| 2045 | return; | 2042 | return; |
| 2046 | 2043 | ||
| 2044 | set_buffer_internal_2 (b); | ||
| 2045 | } | ||
| 2046 | |||
| 2047 | /* Like set_buffer_internal_1, but doesn't check whether B is already | ||
| 2048 | the current buffer. Called upon switch of the current thread, see | ||
| 2049 | post_acquire_global_lock. */ | ||
| 2050 | void set_buffer_internal_2 (register struct buffer *b) | ||
| 2051 | { | ||
| 2052 | register struct buffer *old_buf; | ||
| 2053 | register Lisp_Object tail; | ||
| 2054 | |||
| 2047 | BUFFER_CHECK_INDIRECTION (b); | 2055 | BUFFER_CHECK_INDIRECTION (b); |
| 2048 | 2056 | ||
| 2049 | old_buf = current_buffer; | 2057 | old_buf = current_buffer; |
diff --git a/src/buffer.h b/src/buffer.h index 21ad5e3bc0f..854b5b5dd32 100644 --- a/src/buffer.h +++ b/src/buffer.h | |||
| @@ -1082,6 +1082,7 @@ extern void recenter_overlay_lists (struct buffer *, ptrdiff_t); | |||
| 1082 | extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char **); | 1082 | extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char **); |
| 1083 | extern void validate_region (Lisp_Object *, Lisp_Object *); | 1083 | extern void validate_region (Lisp_Object *, Lisp_Object *); |
| 1084 | extern void set_buffer_internal_1 (struct buffer *); | 1084 | extern void set_buffer_internal_1 (struct buffer *); |
| 1085 | extern void set_buffer_internal_2 (struct buffer *); | ||
| 1085 | extern void set_buffer_temp (struct buffer *); | 1086 | extern void set_buffer_temp (struct buffer *); |
| 1086 | extern Lisp_Object buffer_local_value (Lisp_Object, Lisp_Object); | 1087 | extern Lisp_Object buffer_local_value (Lisp_Object, Lisp_Object); |
| 1087 | extern void record_buffer (Lisp_Object); | 1088 | extern void record_buffer (Lisp_Object); |
diff --git a/src/thread.c b/src/thread.c index 3e61723f0ab..6e9ca2e256b 100644 --- a/src/thread.c +++ b/src/thread.c | |||
| @@ -55,7 +55,6 @@ release_global_lock (void) | |||
| 55 | static void | 55 | static void |
| 56 | post_acquire_global_lock (struct thread_state *self) | 56 | post_acquire_global_lock (struct thread_state *self) |
| 57 | { | 57 | { |
| 58 | Lisp_Object buffer; | ||
| 59 | struct thread_state *prev_thread = current_thread; | 58 | struct thread_state *prev_thread = current_thread; |
| 60 | 59 | ||
| 61 | /* Do this early on, so that code below could signal errors (e.g., | 60 | /* 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) | |||
| 71 | if (prev_thread != NULL) | 70 | if (prev_thread != NULL) |
| 72 | unbind_for_thread_switch (prev_thread); | 71 | unbind_for_thread_switch (prev_thread); |
| 73 | rebind_for_thread_switch (); | 72 | rebind_for_thread_switch (); |
| 74 | } | ||
| 75 | 73 | ||
| 76 | /* We need special handling to re-set the buffer. */ | 74 | /* Set the new thread's current buffer. This needs to be done |
| 77 | XSETBUFFER (buffer, self->m_current_buffer); | 75 | even if it is the same buffer as that of the previous thread, |
| 78 | self->m_current_buffer = 0; | 76 | because of thread-local bindings. */ |
| 79 | set_buffer_internal (XBUFFER (buffer)); | 77 | set_buffer_internal_2 (current_buffer); |
| 78 | } | ||
| 80 | 79 | ||
| 81 | if (!NILP (current_thread->error_symbol)) | 80 | if (!NILP (current_thread->error_symbol)) |
| 82 | { | 81 | { |