Open AliceSync opened 1 year ago
因为Swoole lock设计上是用来实现进程同步的,底层采用的是共享内存,所以只要一个子进程没解锁,剩下的子进程都得阻塞。
因为Swoole lock设计上是用来实现进程同步的,底层采用的是共享内存,所以只要一个子进程没解锁,剩下的子进程都得阻塞。
你应该查看一下代码再说,我是说读写锁在跨进程解锁存在bug,因为swoole-cli的单文件是不存在这个问题的,这个bug只存在于读写锁且属于普通php模式下pecl库安装的swoole才会触发
好的,我再测试看看😁。
好的,我再测试看看😁。
我顺便补充了一下在我本机测试的输出结果,就那串代码,你用swoole-cli和php-cli分别运行一次就知道了,还有很奇怪这个bug只有读写锁会,互斥之类的锁都不会,我也是在自动化覆盖测试卡住才发现的
好的,谢谢
怀疑是 glibc pthread 的 BUG,暂时无法解决。swoole-cli 使用的是 Musl libc ,不存在此问题。需要向 glibc 官方求助了
怀疑是 glibc pthread 的 BUG,暂时无法解决。swoole-cli 使用的是 Musl libc ,不存在此问题。需要向 glibc 官方求助了
韩大佬出现了,我还以为这个bug没人管了呢,我倒是用不上读写锁,只是发现了这个问题反馈了一下,这种奇怪的问题估计上游也不怎么可能快速修复,我c比较捉急,所以这事韩大佬看着来吧
已经代码精简为一个 C++
文件,反馈给了 glibc
官方。
Glibc bug report: https://sourceware.org/bugzilla/show_bug.cgi?id=32220
#include <iostream>
#include <pthread.h>
#include <thread>
#include <unistd.h>
struct RWLockImpl {
pthread_rwlock_t _lock;
pthread_rwlockattr_t attr;
RWLockImpl() {
pthread_rwlockattr_init(&attr);
if (pthread_rwlock_init(&_lock, &attr) != 0) {
throw std::system_error(errno, std::generic_category(),
"pthread_rwlock_init() failed");
}
}
int lock() { return pthread_rwlock_wrlock(&_lock); }
int unlock() { return pthread_rwlock_unlock(&_lock); }
};
struct MutexImpl {
pthread_mutex_t lock_;
pthread_mutexattr_t attr_;
MutexImpl() {
pthread_mutexattr_init(&attr_);
if (pthread_mutex_init(&lock_, &attr_) != 0) {
throw std::system_error(errno, std::generic_category(),
"pthread_mutex_init() failed");
}
}
int lock() { return pthread_mutex_lock(&lock_); }
int unlock() { return pthread_mutex_unlock(&lock_); }
};
int main(int argc, char **argv) {
RWLockImpl impl;
// MutexImpl impl;
std::thread threads[5];
for (int i = 0; i < 5; i++) {
threads[i] = std::thread([&impl, i]() {
if (i == 3) {
sleep(3);
std::cout << i << " try unlock, result=" << impl.unlock() << std::endl;
}
std::cout << i << " try lock " << std::endl;
if (impl.lock() == 0) {
sleep(1);
std::cout << i << " lock success " << std::endl;
}
if (i == 0) {
std::cout << i << " no unlock, exit directly " << std::endl;
pthread_exit(0);
return;
}
std::cout << i << "lock close, result=" << impl.unlock() << std::endl;
pthread_exit(0);
return;
});
}
for (int i = 0; i < 5; i++) {
threads[i].join();
}
}
g++ rwlock.cpp -pthread -std=c++11 -g -o rwlock
./rwlock
0 try lock
2 try lock
1 try lock
4 try lock
0 lock success
0 no unlock, exit directly
3 try unlock, result=0
3 try lock
^C
swoole@swoole-ThinkPad-T470p:~/workspace/debug$
swoole@swoole-ThinkPad-T470p:~/workspace/debug$ ./rwlock
0 try lock
1 try lock
24 try lock try lock
0 lock success
0 no unlock, exit directly
3 try unlock, result=0
3 try lock
3 lock success
3lock close, result=0
4 lock success
4lock close, result=0
2 lock success
2lock close, result=0
1 lock success
1lock close, result=0
swoole@swoole-ThinkPad-T470p:~/workspace/debug$
在线程0 中 lock() 成功,但未解锁直接退出,另外一个线程 unlock()
操作返回了成功,但实际上是无效的。所有线程均进入了死锁状态。
Tps:
What did you do? If possible, provide a simple script for reproducing the error.
What did you expect to see?
php --ri swoole
)?uname -a
&php -v
&gcc -v
) ?