On Fri, 7 Aug 2020 at 01:19, Takashi Sakamoto o-takashi@sakamocchi.jp wrote:
In your case, SNDRV_CTL_IOCTL_ELEM_LOCK looks 'write-lock', therefore any userspace applications can do read operation to the control element locked by the other processes.
To solve the issue, the pair of read/write operations should be done between lock/unlock operations. I can consider about two cases.
A case is that all of applications implements the above. This is already proposed. The case is that the world is universe.
+-----------+-----------+ | process A | process B | +-----------+-----------+ | lock | | | read | | | |lock(EPERM)| reschedule lock/get/put/unlock actions | write | | | |lock(EPERM)| reschedule lock/get/put/unlock actions | unlock | | | | lock | | | read | calculate for new value | | write | | | unlock | +-----------+-----------+
Another case is that a part of application implements the above. Let me drill down the case into two cases. These cases are realistic (sign...):
+-----------+------------+ | process A | process B | +-----------+------------+ | lock | | | read | | | write | | | | read | calculate for new value | |write(EPERM)| | unlock | | | | write | <- expected value +-----------+------------+
+-----------+------------+ | process A | process B | +-----------+------------+ | lock | | | read | | | | read | calculate for new value | write | | | |write(EPERM)| | unlock | | | | write | <- unexpected value +-----------+------------+
The lock/unlock mechanism is not perfect solution as long as any applications perform like the process.
If we can expect the most of applications to be back to read operation at failure of write operation, thing goes well.
+-----------+------------+ | process A | process B | +-----------+------------+ | lock | | | read | | | | read | calculate for new value | write | | | |write(EPERM)| | unlock | | | | read | calculate for new value | | write | <- expected value +-----------+------------+
Oh you were saying, while it is a "write lock in nature", if all the processes considered/involved make use of it (properly, by attempting to lock before *reading*), it would work like a "full" lock. Sorry I wasn't thinking straight.
And I guess there's no point in changing it into a "real" full lock in the kernel anyway as that won't prevent whatever that doesn't make use of it race with each other.
Okay so I suppose that means we can/should at least fix amixer with it for now and see if we can/want to get something better into the kernel. (I am in no position to comment on whether we should do compare-and-swap as I don't know if it's a good idea programmatically speaking, or if there's a huge price in any aspect; all I know is that it *looks* more neat.)
Thanks a lot! Should I file an issue additionally in the alsa-utils github repo btw?
Thanks
Takashi Sakamoto