mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-22 04:30:19 +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,13 +1607,6 @@ fat_mutex_unlock (SCM mutex, SCM cond,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! (SCM_UNBNDP (cond)))
|
|
||||||
{
|
|
||||||
c = SCM_CONDVAR_DATA (cond);
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
int brk = 0;
|
|
||||||
|
|
||||||
if (m->level > 0)
|
if (m->level > 0)
|
||||||
m->level--;
|
m->level--;
|
||||||
if (m->level == 0)
|
if (m->level == 0)
|
||||||
|
@ -1623,54 +1616,46 @@ fat_mutex_unlock (SCM mutex, SCM cond,
|
||||||
m->owner = unblock_from_queue (m->waiting);
|
m->owner = unblock_from_queue (m->waiting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! (SCM_UNBNDP (cond)))
|
||||||
|
{
|
||||||
|
c = SCM_CONDVAR_DATA (cond);
|
||||||
t->block_asyncs++;
|
t->block_asyncs++;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
err = block_self (c->waiting, cond, &m->lock, waittime);
|
err = block_self (c->waiting, cond, &m->lock, waittime);
|
||||||
scm_i_pthread_mutex_unlock (&m->lock);
|
scm_i_pthread_mutex_unlock (&m->lock);
|
||||||
|
|
||||||
if (err == 0)
|
if (err == EINTR)
|
||||||
{
|
{
|
||||||
ret = 1;
|
|
||||||
brk = 1;
|
|
||||||
}
|
|
||||||
else if (err == ETIMEDOUT)
|
|
||||||
{
|
|
||||||
ret = 0;
|
|
||||||
brk = 1;
|
|
||||||
}
|
|
||||||
else if (err != EINTR)
|
|
||||||
{
|
|
||||||
errno = err;
|
|
||||||
scm_syserror (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (brk)
|
|
||||||
{
|
|
||||||
if (relock)
|
|
||||||
scm_lock_mutex_timed (mutex, SCM_UNDEFINED, owner);
|
|
||||||
t->block_asyncs--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
t->block_asyncs--;
|
t->block_asyncs--;
|
||||||
scm_async_click ();
|
scm_async_click ();
|
||||||
|
|
||||||
scm_remember_upto_here_2 (cond, mutex);
|
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
|
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);
|
scm_i_pthread_mutex_unlock (&m->lock);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue