/*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2022 Samsung Electronics Co., Ltd. All rights reserved.
*
* This file is licensed under the terms of MIT License or the Apache License
* Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
void NotifyMe(void);
void CloseSocket(int sock);
+ void RegisterFdForReading(int fd);
+
struct SocketDescription {
bool isListen;
bool isOpen;
SocketDescriptionVector m_socketDescriptionVector;
fd_set m_readSet;
fd_set m_writeSet;
- int m_maxDesc;
- bool m_working;
+ int m_maxDesc = 0;
+ int m_notifyMe;
+ int m_counter = 0;
+ bool m_working = false;
std::mutex m_eventQueueMutex;
std::queue<WriteBuffer> m_writeBufferQueue;
std::queue<ConnectionID> m_closeQueue;
- int m_notifyMe[2];
- int m_counter;
std::priority_queue<Timeout> m_timeoutQueue;
};
/*
- * Copyright (c) 2013-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2013-2022 Samsung Electronics Co., Ltd. All rights reserved.
*
* This file is licensed under the terms of MIT License or the Apache License
* Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
#include <set>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/xattr.h>
#include <signal.h>
+#include <sys/eventfd.h>
#include <sys/select.h>
#include <sys/signalfd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
#include <sys/smack.h>
-#include <sys/wait.h>
-#include <linux/xattr.h>
-#include <sys/un.h>
+#include <sys/socket.h>
#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <errno.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/wait.h>
#include <time.h>
+#include <unistd.h>
#include <systemd/sd-daemon.h>
namespace SecurityManager {
-struct DummyService : public GenericSocketService {
- ServiceDescriptionVector GetServiceDescription() {
- return ServiceDescriptionVector();
- }
- void Event(AcceptEvent &&) { }
- void Event(WriteEvent &&) { }
- void Event(ReadEvent &&) { }
- void Event(CloseEvent &&) { }
-};
-
struct SignalService : public GenericSocketService {
int GetDescriptor() {
LogInfo("set up");
}
};
+void SocketManager::RegisterFdForReading(int fd) {
+ FD_SET(fd, &m_readSet);
+ m_maxDesc = std::max(m_maxDesc, fd);
+}
+
SocketManager::SocketDescription&
SocketManager::CreateDefaultReadSocketDescription(int sock, bool timeout)
{
desc.isTimeout = timeout;
- FD_SET(sock, &m_readSet);
- m_maxDesc = sock > m_maxDesc ? sock : m_maxDesc;
+ RegisterFdForReading(sock);
return desc;
}
SocketManager::SocketManager()
- : m_maxDesc(0)
- , m_working(false)
- , m_counter(0)
{
FD_ZERO(&m_readSet);
FD_ZERO(&m_writeSet);
- if (-1 == pipe(m_notifyMe)) {
+ if ((m_notifyMe = eventfd(0, 0)) < 0) {
int err = errno;
- ThrowMsg(Exception::InitFailed, "Error in pipe: " << GetErrnoString(err));
+ ThrowMsg(Exception::InitFailed, "Error in eventfd: " << GetErrnoString(err));
}
- LogInfo("Pipe: Read desc: " << m_notifyMe[0] << " Write desc: " << m_notifyMe[1]);
-
- auto &desc = CreateDefaultReadSocketDescription(m_notifyMe[0], false);
- desc.service = new DummyService;
-
- // std::thread bases on pthread so this should work fine
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set, SIGPIPE);
- pthread_sigmask(SIG_BLOCK, &set, NULL);
+ LogInfo("Eventfd desc: " << m_notifyMe);
+ RegisterFdForReading(m_notifyMe);
// add support for TERM signal (passed from systemd)
auto *signalService = new SignalService;
if (m_socketDescriptionVector[i].isOpen)
close(i);
- // All socket except one were closed. Now pipe input must be closed.
- close(m_notifyMe[1]);
+ // All service sockets have been closed. Close internal descriptors.
+ close(m_notifyMe);
}
void SocketManager::ReadyForAccept(int sock) {
case EINTR:
// select will trigger write once again, nothing to do
break;
- case EPIPE:
default:
LogError("Error during write: " << GetErrnoString(err));
CloseSocket(sock);
sd_notify(0, "READY=1");
m_working = true;
- while (m_working) {
+ for (;;) {
fd_set readSet = m_readSet;
fd_set writeSet = m_writeSet;
}
continue;
}
+
+ if (FD_ISSET(m_notifyMe, &readSet)) {
+ if (!m_working)
+ return;
+ eventfd_t dummyValue;
+ TEMP_FAILURE_RETRY(eventfd_read(m_notifyMe, &dummyValue));
+ FD_CLR(m_notifyMe, &readSet);
+ }
+
for (int i = 0; i < m_maxDesc+1 && ret; ++i) {
if (FD_ISSET(i, &readSet)) {
ReadyForRead(i);
}
void SocketManager::NotifyMe() {
- TEMP_FAILURE_RETRY(write(m_notifyMe[1], "You have message ;-)", 1));
+ TEMP_FAILURE_RETRY(eventfd_write(m_notifyMe, 1));
}
void SocketManager::ProcessQueue() {