@@ -127,6 +127,15 @@ void msgpack_buffer_mark(void *ptr)
127127
128128bool _msgpack_buffer_shift_chunk (msgpack_buffer_t * b )
129129{
130+ if (b -> rmem_owner == & b -> head -> mem ) {
131+ /* the chunk that owns the rmem page is going away and takes the page
132+ * with it. don't carve the remaining space out of a page that is
133+ * already back in the pool. */
134+ b -> rmem_end = NULL ;
135+ b -> rmem_last = NULL ;
136+ b -> rmem_owner = NULL ;
137+ }
138+
130139 _msgpack_buffer_chunk_destroy (b -> head );
131140
132141 if (b -> head == & b -> tail ) {
@@ -264,6 +273,18 @@ static inline msgpack_buffer_chunk_t* _msgpack_buffer_alloc_new_chunk(msgpack_bu
264273 return chunk ;
265274}
266275
276+ /* b->tail is copied into nc and then rebuilt, so the rmem page pointer moves
277+ * to nc. the owner has to follow it: if it kept pointing at b->tail.mem, the
278+ * transfer in _msgpack_buffer_chunk_malloc would degenerate into a
279+ * self-assignment and the page would be released by nc while the rebuilt tail
280+ * is still reading from it. */
281+ static inline void _msgpack_buffer_transfer_rmem_owner (msgpack_buffer_t * b , msgpack_buffer_chunk_t * nc )
282+ {
283+ if (b -> rmem_owner == & b -> tail .mem ) {
284+ b -> rmem_owner = & nc -> mem ;
285+ }
286+ }
287+
267288static inline void _msgpack_buffer_add_new_chunk (msgpack_buffer_t * b )
268289{
269290 if (b -> head == & b -> tail ) {
@@ -275,6 +296,7 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
275296 msgpack_buffer_chunk_t * nc = _msgpack_buffer_alloc_new_chunk (b );
276297
277298 * nc = b -> tail ;
299+ _msgpack_buffer_transfer_rmem_owner (b , nc );
278300 b -> head = nc ;
279301 nc -> next = & b -> tail ;
280302
@@ -295,6 +317,7 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
295317
296318 /* rebuild tail */
297319 * nc = b -> tail ;
320+ _msgpack_buffer_transfer_rmem_owner (b , nc );
298321 before_tail -> next = nc ;
299322 nc -> next = & b -> tail ;
300323 }
0 commit comments