mirror of https://git.kore.io/kore.git
Fix two concurrency issues with kore.lock().
1) If a coroutine was waken up by another releasing a lock it was waiting on we would incorrectly remove the pylock_op when the newly awoken coroutine hits the iternext for pylock. 2) If a coroutine attempts to grab a lock it was woken up for only to fail we did not properly rearm the coroutine to be woken up later to try again.
This commit is contained in:
parent
5f0153ba0e
commit
c2d9f1413c
15
src/python.c
15
src/python.c
|
@ -2682,6 +2682,7 @@ pylock_do_release(struct pylock *lock)
|
||||||
if (op->locking == 0)
|
if (op->locking == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
op->active = 0;
|
||||||
TAILQ_REMOVE(&op->lock->ops, op, list);
|
TAILQ_REMOVE(&op->lock->ops, op, list);
|
||||||
|
|
||||||
if (op->coro->request != NULL)
|
if (op->coro->request != NULL)
|
||||||
|
@ -2689,7 +2690,6 @@ pylock_do_release(struct pylock *lock)
|
||||||
else
|
else
|
||||||
python_coro_wakeup(op->coro);
|
python_coro_wakeup(op->coro);
|
||||||
|
|
||||||
op->active = 0;
|
|
||||||
Py_DECREF((PyObject *)op);
|
Py_DECREF((PyObject *)op);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2733,14 +2733,27 @@ pylock_op_iternext(struct pylock_op *op)
|
||||||
pylock_do_release(op->lock);
|
pylock_do_release(op->lock);
|
||||||
} else {
|
} else {
|
||||||
if (op->lock->owner != NULL) {
|
if (op->lock->owner != NULL) {
|
||||||
|
/*
|
||||||
|
* We could be beat by another coroutine that grabbed
|
||||||
|
* the lock even if we were the one woken up for it.
|
||||||
|
*/
|
||||||
|
if (op->active == 0) {
|
||||||
|
op->active = 1;
|
||||||
|
TAILQ_INSERT_HEAD(&op->lock->ops, op, list);
|
||||||
|
Py_INCREF((PyObject *)op);
|
||||||
|
}
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
op->lock->owner = coro_running;
|
op->lock->owner = coro_running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (op->active) {
|
||||||
op->active = 0;
|
op->active = 0;
|
||||||
TAILQ_REMOVE(&op->lock->ops, op, list);
|
TAILQ_REMOVE(&op->lock->ops, op, list);
|
||||||
|
Py_DECREF((PyObject *)op);
|
||||||
|
}
|
||||||
|
|
||||||
PyErr_SetNone(PyExc_StopIteration);
|
PyErr_SetNone(PyExc_StopIteration);
|
||||||
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
Loading…
Reference in New Issue