macOS:在其套接字上调用 fd_set 后 DNSSD 崩溃
macOS: DNSSD crash after calling fd_set on its socket
我有以下代码,它在调用 FD_SET 时使我的程序崩溃。
void handleEvents(DNSServiceRef service, const int32_t timeout)
{
if (!service)
return;
const int fd = DNSServiceRefSockFD( service );
const int nfds = fd + 1;
if (fd < 0)
return;
int32_t result = servus::Result::PENDING;
while(result == servus::Result::PENDING)
{
fd_set fdSet;
FD_ZERO( &fdSet );
FD_SET( fd, &fdSet ); /// < The crash occurs here
const int result = ::select( nfds, &fdSet, 0, 0, 0);
switch (result)
{
case 0: // timeout
return;
case -1: // error
std::cerr << "Select error: " << strerror( errno ) << " (" << errno
<< ")" << std::endl;
if( errno != EINTR )
{
withdraw();
return;
}
break;
default:
if(FD_ISSET( fd, &fdSet ))
{
const auto error = DNSServiceProcessResult(service);
if(error != kDNSServiceErr_NoError)
{
std::cerr << "DNSServiceProcessResult error: " << error << std::endl;
withdraw();
return;
}
}
break;
}
}
}
崩溃日志是:
Exception Type: EXC_GUARD
Exception Codes: 0x6000000000000012, 0x0000000000000002
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: LIBSYSTEM, [0x2]
External Modification Warnings:
Debugger attached to process.
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x00007fff6d62d96e os_fault_with_payload + 10
1 libsystem_kernel.dylib 0x00007fff6d62e451 __darwin_check_fd_set_overflow.cold.2 + 31
2 libsystem_kernel.dylib 0x00007fff6d61967c __darwin_check_fd_set_overflow + 68
3 score 0x00000001004f097e handleEvents(_DNSServiceRef_t*, int) + 302
我真的不明白哪里出了问题-导致崩溃的“关键链”似乎是
const int fd = DNSServiceRefSockFD( service );
const int nfds = fd + 1;
int result = 0;
fd_set fdSet;
FD_ZERO( &fdSet );
FD_SET( fd, &fdSet ); /// < The crash occurs here
result = ::select( nfds, &fdSet, 0, 0, 0);
fd_set fdSet;
FD_ZERO( &fdSet );
FD_SET( fd, &fdSet ); /// < or here
这种情况下的实际问题是我打开了太多的文件描述符,这可以通过使用以下代码增加 rlimit 来解决:
void setup_min_fd(int min_fds)
{
struct rlimit rlim;
if (getrlimit(RLIMIT_NOFILE, &rlim) != 0)
return;
if (rlim.rlim_cur > rlim_t(min_fds))
return;
rlim.rlim_cur = rlim.min_fds;
setrlimit(RLIMIT_NOFILE, &rlim);
}
我有以下代码,它在调用 FD_SET 时使我的程序崩溃。
void handleEvents(DNSServiceRef service, const int32_t timeout)
{
if (!service)
return;
const int fd = DNSServiceRefSockFD( service );
const int nfds = fd + 1;
if (fd < 0)
return;
int32_t result = servus::Result::PENDING;
while(result == servus::Result::PENDING)
{
fd_set fdSet;
FD_ZERO( &fdSet );
FD_SET( fd, &fdSet ); /// < The crash occurs here
const int result = ::select( nfds, &fdSet, 0, 0, 0);
switch (result)
{
case 0: // timeout
return;
case -1: // error
std::cerr << "Select error: " << strerror( errno ) << " (" << errno
<< ")" << std::endl;
if( errno != EINTR )
{
withdraw();
return;
}
break;
default:
if(FD_ISSET( fd, &fdSet ))
{
const auto error = DNSServiceProcessResult(service);
if(error != kDNSServiceErr_NoError)
{
std::cerr << "DNSServiceProcessResult error: " << error << std::endl;
withdraw();
return;
}
}
break;
}
}
}
崩溃日志是:
Exception Type: EXC_GUARD
Exception Codes: 0x6000000000000012, 0x0000000000000002
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: LIBSYSTEM, [0x2]
External Modification Warnings:
Debugger attached to process.
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x00007fff6d62d96e os_fault_with_payload + 10
1 libsystem_kernel.dylib 0x00007fff6d62e451 __darwin_check_fd_set_overflow.cold.2 + 31
2 libsystem_kernel.dylib 0x00007fff6d61967c __darwin_check_fd_set_overflow + 68
3 score 0x00000001004f097e handleEvents(_DNSServiceRef_t*, int) + 302
我真的不明白哪里出了问题-导致崩溃的“关键链”似乎是
const int fd = DNSServiceRefSockFD( service );
const int nfds = fd + 1;
int result = 0;
fd_set fdSet;
FD_ZERO( &fdSet );
FD_SET( fd, &fdSet ); /// < The crash occurs here
result = ::select( nfds, &fdSet, 0, 0, 0);
fd_set fdSet;
FD_ZERO( &fdSet );
FD_SET( fd, &fdSet ); /// < or here
这种情况下的实际问题是我打开了太多的文件描述符,这可以通过使用以下代码增加 rlimit 来解决:
void setup_min_fd(int min_fds)
{
struct rlimit rlim;
if (getrlimit(RLIMIT_NOFILE, &rlim) != 0)
return;
if (rlim.rlim_cur > rlim_t(min_fds))
return;
rlim.rlim_cur = rlim.min_fds;
setrlimit(RLIMIT_NOFILE, &rlim);
}