访问子线程中的套接字描述符时"Bad file descriptor"
"Bad file descriptor" when accessing socket descriptor in child thread
当尝试访问子线程中的套接字描述符(使用bind()或listen())时,我得到错误:
错误的文件描述符
以下是代码(忽略标题):
class task {
private:
std::int32_t socFd;
std::string path;
char buffer[MAX_SOC_BUFFER];
struct sockaddr_un socAddr;
public:
void init() {
if ((socFd = socket((std::int32_t)AF_UNIX, (std::int32_t)SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
socAddr.sun_family = AF_UNIX;
strcpy(socAddr.sun_path, getSocPath().c_str());
}
task(const std::string& path) : path{path}
{
init();
}
auto getSocketFd() ->decltype(socFd) {
return socFd;
}
const std::string& getSocPath() {
return path;
}
auto getSocAddr() -> decltype(socAddr)&
{
return socAddr;
}
char* getBuff() {
return buffer;
}
virtual ~ task() {
close(getSocketFd());
}
};
class server_task : public task{
public:
void init () {
::unlink(getSocPath().c_str());
size_t len = sizeof(getSocAddr());
if (bind(getSocketFd(), (struct sockaddr *)&(getSocAddr()), len) == -1) {
perror("bind");
exit(1);
}
}
server_task(const std::string& path) : task(path)
{
init();
}
void operator()() {
struct sockaddr_un remote;
if (listen(getSocketFd(), 5) == -1) {
perror("listen");
exit(1);
}
for(;;) {
int done, n, socFd2;
printf("Waiting for a connection...n");
socklen_t t = sizeof(remote);
if ((socFd2 = accept(getSocketFd(), (struct sockaddr *)&remote, &t)) == -1) {
perror("accept");
exit(1);
}
printf("Connected.n");
done = 0;
do {
n = recv(socFd2, getBuff(), 100, 0);
if (n <= 0) {
if (n < 0) perror("recv");
done = 1;
}
if (!done) {
std::string buffStr(getBuff());
std::transform(buffStr.begin(), buffStr.end(),buffStr.begin(), ::toupper);
if (send(socFd2, buffStr.c_str(), n, 0) < 0) {
perror("send");
done = 1;
}
}
} while (!done);
close(socFd2);
}
}
};
int main(){
std::vector<std::thread> threads;
server_task server("/tmp/temp_socket");
threads.push_back(std::thread(server));
for(auto& thread : threads)
thread.join();
return 0;
}
如果我将main()
功能更改为:
int main(){
server_task server("/tmp/temp_socket");
server();
return 0;
}
没有发生这样的错误。据我所知,文件描述符表在父进程及其子线程之间共享,因此套接字句柄应该是有效的。
我做错了什么?
threads.push_back(std::thread(server));
这会创建server
对象的至少一个副本,可能是多个副本,并且因为您没有定义副本构造函数,所以每个副本都共享同一个套接字,第一个超出范围的副本会关闭套接字。当新线程启动时,临时副本已经被销毁并关闭了套接字,因此在新线程中运行的server_task
的副本指的是一个关闭的套接字。
您应该为task
和server_task
类型定义一个移动构造函数,以便套接字的所有权被转移而不是复制,然后将对象移动到线程中:
thread.push_back(std::thread(std::move(server)));
否则,您应该通过引用将服务器传递给新线程,这样就没有副本:
thread.push_back(std::thread(std::ref(server)));
相关文章:
- Seg Fault Issue C++ (file IO / getline)
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- Android NDK clang 编译器错误在 Windows 上显示'No such file or directory'
- File.cpp.o:OpenPose 标志 CMakeFiles/.. 的多重定义/main.cpp.o:首先在这里定
- Visual Studio C++ Project File CustomBuild Task: Filter Outp
- 已解决 - C++ 的崇高文本中的"fatal error: opencv: no such file or directory"
- 可视化 如何在C++中将字符数组转换为 FILE 类型
- 如何在从文件中读取整数时使用 file.eof()?
- "No such file or directory" C++标头问题
- 使用 sftp_open() 使用 C++ 中的 SFTP libssh 将文件从本地复制到远程时,File 返回 N
- Visual Studio "fatal error LNK1104: cannot open file"未使用或包含的库
- 使用来自 Excel VBA 的 C++ dll 时"Bad DLL calling convention" - 如何解决?
- typedef vector size_type in header file
- make 命令创建 .file,但不创建应用程序文件
- 在多线程环境中,什么可能导致"bad file descriptor"?
- 尝试使用 execp、dup2 和管道实现 shell,挂起或"bad file descriptor"
- 使用 boost::asio 和 boost::thread 时"Bad file descriptor"
- 生成文件'fdopen: Bad file descriptor'错误
- Bad Linux Memory Map File Performance with Random Access C++ & Python
- 访问子线程中的套接字描述符时"Bad file descriptor"