Skip to content

Commit 755548b

Browse files
jumpsiegeltopointon-jump
authored andcommitted
para_pool_fix: bug fix for race condition in para_pool_acquire
1 parent e7cdd7f commit 755548b

File tree

1 file changed

+20
-11
lines changed

1 file changed

+20
-11
lines changed

src/util/tmpl/fd_pool_para.c

+20-11
Original file line numberDiff line numberDiff line change
@@ -673,18 +673,27 @@ POOL_(acquire)( POOL_(t) * join,
673673

674674
ulong ele_nxt = POOL_(private_idx)( ele0[ ele_idx ].POOL_NEXT );
675675

676-
if( FD_UNLIKELY( (ele_nxt>=ele_max) & (!POOL_(idx_is_null)( ele_nxt )) ) ) { /* opt for not corrupt */
677-
err = FD_POOL_ERR_CORRUPT;
678-
break;
679-
}
680-
681-
ulong new_ver_top = POOL_(private_vidx)( ver+2UL, ele_nxt );
682-
683-
if( FD_LIKELY( POOL_(private_cas)( _v, ver_top, new_ver_top )==ver_top ) ) { /* opt for low contention */
684-
ele = ele0 + ele_idx;
685-
break;
676+
if( FD_UNLIKELY( (ele_nxt>=ele_max) & (!POOL_(idx_is_null)( ele_nxt )) ) ) { /* ele_nxt is invalid, opt for valid */
677+
/* It is possible that another thread acquired ele_idx and
678+
repurposed ele_idx's POOL_NEXT (storing something in it that
679+
isn't a valid pool value) between when we read ver_top and
680+
when we read ele_idx's POOL_NEXT above. If so, the pool
681+
version would be changed from what we read above. We thus
682+
only signal ERR_CORRUPT if the version number hasn't changed
683+
since we read it. */
684+
685+
if( FD_UNLIKELY( POOL_(private_vidx_ver)( *_v )==ver ) ) {
686+
err = FD_POOL_ERR_CORRUPT;
687+
break;
688+
}
689+
} else { /* ele_nxt is valid */
690+
ulong new_ver_top = POOL_(private_vidx)( ver+2UL, ele_nxt );
691+
692+
if( FD_LIKELY( POOL_(private_cas)( _v, ver_top, new_ver_top )==ver_top ) ) { /* opt for low contention */
693+
ele = ele0 + ele_idx;
694+
break;
695+
}
686696
}
687-
688697
} else if( FD_UNLIKELY( !blocking ) ) { /* opt for blocking */
689698

690699
err = FD_POOL_ERR_AGAIN;

0 commit comments

Comments
 (0)