mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
Fix fat_mutex owner corruption and other problems in fat_mutex_unlock.
Fixes <https://debbugs.gnu.org/22152>. Reported by Iwan Aucamp <aucampia@gmail.com>. * libguile/threads.c (fat_mutex_unlock): Avoid repeatedly decrementing m->level and changing the owner of the mutex when 'block_self' returns EINTR. Unblock asyncs before calling scm_syserror. Refactor the code to clarify the EINTR loop, and to make it more apparent that the async blocks and unblocks are balanced.
This commit is contained in:
parent
4b60562820
commit
1e86dc32a4
1 changed files with 36 additions and 51 deletions
|
@ -1607,70 +1607,55 @@ fat_mutex_unlock (SCM mutex, SCM cond,
|
|||
}
|
||||
}
|
||||
|
||||
if (m->level > 0)
|
||||
m->level--;
|
||||
if (m->level == 0)
|
||||
{
|
||||
/* Change the owner of MUTEX. */
|
||||
t->mutexes = scm_delq_x (mutex, t->mutexes);
|
||||
m->owner = unblock_from_queue (m->waiting);
|
||||
}
|
||||
|
||||
if (! (SCM_UNBNDP (cond)))
|
||||
{
|
||||
c = SCM_CONDVAR_DATA (cond);
|
||||
while (1)
|
||||
t->block_asyncs++;
|
||||
|
||||
do
|
||||
{
|
||||
int brk = 0;
|
||||
|
||||
if (m->level > 0)
|
||||
m->level--;
|
||||
if (m->level == 0)
|
||||
{
|
||||
/* Change the owner of MUTEX. */
|
||||
t->mutexes = scm_delq_x (mutex, t->mutexes);
|
||||
m->owner = unblock_from_queue (m->waiting);
|
||||
}
|
||||
|
||||
t->block_asyncs++;
|
||||
|
||||
err = block_self (c->waiting, cond, &m->lock, waittime);
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
ret = 1;
|
||||
brk = 1;
|
||||
}
|
||||
else if (err == ETIMEDOUT)
|
||||
{
|
||||
ret = 0;
|
||||
brk = 1;
|
||||
}
|
||||
else if (err != EINTR)
|
||||
{
|
||||
errno = err;
|
||||
scm_syserror (NULL);
|
||||
}
|
||||
if (err == EINTR)
|
||||
{
|
||||
t->block_asyncs--;
|
||||
scm_async_click ();
|
||||
|
||||
if (brk)
|
||||
{
|
||||
if (relock)
|
||||
scm_lock_mutex_timed (mutex, SCM_UNDEFINED, owner);
|
||||
t->block_asyncs--;
|
||||
break;
|
||||
}
|
||||
scm_remember_upto_here_2 (cond, mutex);
|
||||
|
||||
t->block_asyncs--;
|
||||
scm_async_click ();
|
||||
|
||||
scm_remember_upto_here_2 (cond, mutex);
|
||||
|
||||
scm_i_scm_pthread_mutex_lock (&m->lock);
|
||||
scm_i_scm_pthread_mutex_lock (&m->lock);
|
||||
t->block_asyncs++;
|
||||
}
|
||||
}
|
||||
while (err == EINTR);
|
||||
|
||||
if (err == 0)
|
||||
ret = 1;
|
||||
else if (err == ETIMEDOUT)
|
||||
ret = 0;
|
||||
else
|
||||
{
|
||||
t->block_asyncs--;
|
||||
errno = err;
|
||||
scm_syserror (NULL);
|
||||
}
|
||||
|
||||
if (relock)
|
||||
scm_lock_mutex_timed (mutex, SCM_UNDEFINED, owner);
|
||||
t->block_asyncs--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m->level > 0)
|
||||
m->level--;
|
||||
if (m->level == 0)
|
||||
{
|
||||
/* Change the owner of MUTEX. */
|
||||
t->mutexes = scm_delq_x (mutex, t->mutexes);
|
||||
m->owner = unblock_from_queue (m->waiting);
|
||||
}
|
||||
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
ret = 1;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue