KQueueEngine::KQueueEngine(InspIRCd* Instance) : SocketEngine(Instance)
{
+ this->RecoverFromFork();
+}
+
+void KQueueEngine::RecoverFromFork()
+{
+ /*
+ * The only bad thing about kqueue is that its fd cant survive a fork and is not inherited.
+ * BUM HATS.
+ *
+ */
EngineHandle = kqueue();
if (EngineHandle == -1)
{
ServerInstance->Log(SPARSE,"ERROR: this is a fatal error, exiting now.");
printf("ERROR: Could not initialize socket engine. Your kernel probably does not have the proper features.");
printf("ERROR: this is a fatal error, exiting now.");
- InspIRCd::Exit(EXIT_STATUS_SOCKETENGINE);
+ ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
}
CurrentSetSize = 0;
}
KQueueEngine::~KQueueEngine()
{
- ServerInstance->Log(DEBUG,"KQueueEngine::~KQueueEngine()");
- close(EngineHandle);
+ this->Close(EngineHandle);
}
bool KQueueEngine::AddFd(EventHandler* eh)
{
int fd = eh->GetFd();
- ServerInstance->Log(DEBUG,"KQueueEngine::AddFd(%d)",fd);
-
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
- {
- ServerInstance->Log(DEBUG,"ERROR: FD of %d added above max of %d",fd,MAX_DESCRIPTORS);
return false;
- }
+
if (GetRemainingFds() <= 1)
- {
- ServerInstance->Log(DEBUG,"ERROR: System out of file descriptors!");
return false;
- }
if (ref[fd])
- {
- ServerInstance->Log(DEBUG,"ERROR: Slot already occupied");
return false;
- }
ref[fd] = eh;
- ServerInstance->Log(DEBUG,"Add socket %d",fd);
struct kevent ke;
- ServerInstance->Log(DEBUG,"kqueue: Add socket to events, kq=%d socket=%d",EngineHandle,fd);
EV_SET(&ke, fd, eh->Readable() ? EVFILT_READ : EVFILT_WRITE, EV_ADD, 0, 0, NULL);
int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
if (i == -1)
- {
- ServerInstance->Log(DEBUG,"kqueue: List insertion failure!");
return false;
- }
CurrentSetSize++;
+
+ ServerInstance->Log(DEBUG,"New file descriptor: %d", fd);
return true;
}
-bool KQueueEngine::DelFd(EventHandler* eh)
+bool KQueueEngine::DelFd(EventHandler* eh, bool force)
{
int fd = eh->GetFd();
- ServerInstance->Log(DEBUG,"KQueueEngine::DelFd(%d)",fd);
-
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
return false;
EV_SET(&ke, eh->GetFd(), EVFILT_READ, EV_DELETE, 0, 0, NULL);
int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
-
+
EV_SET(&ke, eh->GetFd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
int j = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
- if ((j < 0) && (i < 0))
+ if ((j < 0) && (i < 0) && !force)
return false;
CurrentSetSize--;
ref[fd] = NULL;
+ ServerInstance->Log(DEBUG,"Remove file descriptor: %d", fd);
return true;
}
*/
struct kevent ke;
EV_SET(&ke, eh->GetFd(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, NULL);
- int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
- if (i == -1)
- {
- ServerInstance->Log(DEBUG,"kqueue: Unable to set fd %d for wanting write", eh->GetFd());
- }
+ kevent(EngineHandle, &ke, 1, 0, 0, NULL);
}
int KQueueEngine::GetMaxFds()
int KQueueEngine::DispatchEvents()
{
- ts.tv_nsec = 5000L;
- ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ ts.tv_sec = 1;
int i = kevent(EngineHandle, NULL, 0, &ke_list[0], MAX_DESCRIPTORS, &ts);
for (int j = 0; j < i; j++)
{
- ServerInstance->Log(DEBUG,"Handle %s event on fd %d",ke_list[j].flags & EVFILT_WRITE ? "write" : "read", ke_list[j].ident);
if (ke_list[j].flags & EV_EOF)
{
- ServerInstance->Log(DEBUG,"kqueue: Error on FD %d", ke_list[j].ident);
/* We love you kqueue, oh yes we do *sings*!
* kqueue gives us the error number directly in the EOF state!
* Unlike smelly epoll and select, where we have to getsockopt
}
if (ke_list[j].flags & EVFILT_WRITE)
{
- /* This looks wrong but its right. As above, theres no modify
+ /* This looks wrong but its right. As above, theres no modify
* call in kqueue. See the manpage.
*/
struct kevent ke;
EV_SET(&ke, ke_list[j].ident, EVFILT_READ, EV_ADD, 0, 0, NULL);
- int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
- if (i == -1)
- {
- ServerInstance->Log(DEBUG,"kqueue: Unable to set fd %d back to just wanting to read!", ke_list[j].ident);
- }
+ kevent(EngineHandle, &ke, 1, 0, 0, NULL);
if (ref[ke_list[j].ident])
ref[ke_list[j].ident]->HandleEvent(EVENT_WRITE);
}