1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "uds/service_dispatcher.h" 2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <errno.h> 4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <log/log.h> 5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/epoll.h> 6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/eventfd.h> 7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "pdx/service.h" 9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "uds/service_endpoint.h" 10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostatic const int kMaxEventsPerLoop = 128; 12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android { 14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx { 15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace uds { 16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::unique_ptr<pdx::ServiceDispatcher> ServiceDispatcher::Create() { 18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko std::unique_ptr<ServiceDispatcher> dispatcher{new ServiceDispatcher()}; 19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (!dispatcher->epoll_fd_ || !dispatcher->event_fd_) { 20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko dispatcher.reset(); 21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return std::move(dispatcher); 24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoServiceDispatcher::ServiceDispatcher() { 27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); 28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (!event_fd_) { 29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ALOGE("Failed to create event fd because: %s\n", strerror(errno)); 30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return; 31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 33409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko epoll_fd_.Reset(epoll_create1(EPOLL_CLOEXEC)); 34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (!epoll_fd_) { 35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ALOGE("Failed to create epoll fd because: %s\n", strerror(errno)); 36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return; 37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Use "this" as a unique pointer to distinguish the event fd from all 40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // the other entries that point to instances of Service. 41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko epoll_event event; 42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko event.events = EPOLLIN; 43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko event.data.ptr = this; 44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, event_fd_.Get(), &event) < 0) { 46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ALOGE("Failed to add event fd to epoll fd because: %s\n", strerror(errno)); 47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // Close the fds here and signal failure to the factory method. 49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko event_fd_.Close(); 50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko epoll_fd_.Close(); 51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoServiceDispatcher::~ServiceDispatcher() { SetCanceled(true); } 55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint ServiceDispatcher::ThreadEnter() { 57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko std::lock_guard<std::mutex> autolock(mutex_); 58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (canceled_) 60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return -EBUSY; 61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko thread_count_++; 63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return 0; 64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid ServiceDispatcher::ThreadExit() { 67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko std::lock_guard<std::mutex> autolock(mutex_); 68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko thread_count_--; 69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko condition_.notify_one(); 70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint ServiceDispatcher::AddService(const std::shared_ptr<Service>& service) { 73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (service->endpoint()->GetIpcTag() != Endpoint::kIpcTag) 74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return -EINVAL; 75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko std::lock_guard<std::mutex> autolock(mutex_); 77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko auto* endpoint = static_cast<Endpoint*>(service->endpoint()); 79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko epoll_event event; 80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko event.events = EPOLLIN; 81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko event.data.ptr = service.get(); 82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, endpoint->epoll_fd(), &event) < 84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 0) { 85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ALOGE("Failed to add service to dispatcher because: %s\n", strerror(errno)); 86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return -errno; 87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko services_.push_back(service); 90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return 0; 91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint ServiceDispatcher::RemoveService(const std::shared_ptr<Service>& service) { 94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (service->endpoint()->GetIpcTag() != Endpoint::kIpcTag) 95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return -EINVAL; 96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko std::lock_guard<std::mutex> autolock(mutex_); 98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko // It's dangerous to remove a service while other threads may be using it. 100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (thread_count_ > 0) 101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return -EBUSY; 102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko epoll_event dummy; // See BUGS in man 2 epoll_ctl. 104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko auto* endpoint = static_cast<Endpoint*>(service->endpoint()); 106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, endpoint->epoll_fd(), &dummy) < 107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 0) { 108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ALOGE("Failed to remove service from dispatcher because: %s\n", 109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko strerror(errno)); 110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return -errno; 111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko services_.remove(service); 114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return 0; 115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint ServiceDispatcher::ReceiveAndDispatch() { return ReceiveAndDispatch(-1); } 118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint ServiceDispatcher::ReceiveAndDispatch(int timeout) { 120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko int ret = ThreadEnter(); 121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (ret < 0) 122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return ret; 123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko epoll_event events[kMaxEventsPerLoop]; 125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko int count = epoll_wait(epoll_fd_.Get(), events, kMaxEventsPerLoop, timeout); 127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (count <= 0) { 128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ALOGE_IF(count < 0, "Failed to wait for epoll events because: %s\n", 129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko strerror(errno)); 130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ThreadExit(); 131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return count < 0 ? -errno : -ETIMEDOUT; 132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko for (int i = 0; i < count; i++) { 135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (events[i].data.ptr == this) { 136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ThreadExit(); 137e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return -EBUSY; 138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } else { 139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko Service* service = static_cast<Service*>(events[i].data.ptr); 140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ALOGI_IF(TRACE, "Dispatching message: fd=%d\n", 142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko static_cast<Endpoint*>(service->endpoint())->epoll_fd()); 143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko service->ReceiveAndDispatch(); 144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ThreadExit(); 148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return 0; 149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint ServiceDispatcher::EnterDispatchLoop() { 152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko int ret = ThreadEnter(); 153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (ret < 0) 154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return ret; 155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko epoll_event events[kMaxEventsPerLoop]; 157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko while (!IsCanceled()) { 159e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko int count = epoll_wait(epoll_fd_.Get(), events, kMaxEventsPerLoop, -1); 160e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (count < 0 && errno != EINTR) { 161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ALOGE("Failed to wait for epoll events because: %s\n", strerror(errno)); 162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ThreadExit(); 163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return -errno; 164e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko for (int i = 0; i < count; i++) { 167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (events[i].data.ptr == this) { 168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ThreadExit(); 169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return -EBUSY; 170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } else { 171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko Service* service = static_cast<Service*>(events[i].data.ptr); 172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ALOGI_IF(TRACE, "Dispatching message: fd=%d\n", 174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko static_cast<Endpoint*>(service->endpoint())->epoll_fd()); 175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko service->ReceiveAndDispatch(); 176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko ThreadExit(); 181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko return 0; 182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 184e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid ServiceDispatcher::SetCanceled(bool cancel) { 185e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko std::unique_lock<std::mutex> lock(mutex_); 186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko canceled_ = cancel; 187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko if (canceled_ && thread_count_ > 0) { 189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko eventfd_write(event_fd_.Get(), 1); // Signal threads to quit. 190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko condition_.wait(lock, [this] { return !(canceled_ && thread_count_ > 0); }); 192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko eventfd_t value; 194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko eventfd_read(event_fd_.Get(), &value); // Unsignal. 195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko } 196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} 197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool ServiceDispatcher::IsCanceled() const { return canceled_; } 199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} // namespace uds 201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} // namespace pdx 202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} // namespace android 203