Subject: bug#716: Bug in buffer-swap-text

From: Jason Rumney <[email-masked]>
Date: Tue, 23 Dec 2008 22:51:34 +0800

Jason Rumney wrote:
> One possible variable here is the way that buffer space is allocated. 
> On Windows, it seems REL_ALLOC is defined. I presume GNU/Linux defines 
> USE_MMAP_FOR_BUFFERS which would cause it to take a different code 
> path around the point where we see a crash on Windows, and as Magnus 
> Henoch saw on NetBSD/powerpc also (though we don't have a stack trace 
> for that crash, so can't tell for sure it is crashing in the same place).
The following patch seems to fix the problem, does it look correct to 
others who might understand ralloc.c and buffer_swap_text better than I do?

Index: buffer.c
===================================================================
RCS file: /sources/emacs/emacs/src/buffer.c,v
retrieving revision 1.575
diff -r1.575 buffer.c
2184a2185,2189
> #ifdef REL_ALLOC
> extern void r_alloc_prepare_to_swap_pointers P_ ((POINTER_TYPE **,
> 						  POINTER_TYPE **));
> #endif
> 
2222a2228,2232
> #ifdef REL_ALLOC
>   r_alloc_prepare_to_swap_pointers (&current_buffer->own_text.beg,
> 				    &other_buffer->own_text.beg);
> #endif
> 
Index: ralloc.c
===================================================================
RCS file: /sources/emacs/emacs/src/ralloc.c,v
retrieving revision 1.69
diff -r1.69 ralloc.c
1225a1226,1248
> /* Swap relocatable data between two pointers.
>    This is used by buffer_swap_text.  Since buffer_swap_text swaps the
>    whole text structure in one go, this function has been written to only
>    update the internal pointers back to the variables, ready for when the
>    swap is actually done.  It must be called before the pointers are
>    swapped so that the state is consistent when find_bloc is called.  */
> void
> r_alloc_prepare_to_swap_pointers (p1, p2)
>      POINTER *p1, *p2;
> {
>   bloc_ptr bloc1, bloc2;
>   bloc1 = find_bloc (p1);
>   bloc2 = find_bloc (p2);
>   if (bloc1 == NIL_BLOC || bloc2 == NIL_BLOC)
>     abort ();
> 
>   /* Swap internal pointers back to the variables.  */
>   bloc1->variable = p2;
>   bloc2->variable = p1;
> 
>   /* It would be cleaner to do the actual swap here too, but it would
>      complicate buffer_swap_text.  */
> }