Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(720)

Unified Diff: native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc

Issue 23005005: [NaCl SDK] nacl_io: Add initial implementations of kill and signal (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
index 1a0542c12d62f23628ee7add15ff3fe39c094aab..cf47d287d229caea20609a0f46d638aef2a3c4a0 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -14,10 +14,12 @@
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
+#include <unistd.h>
#include <iterator>
#include <string>
+#include "nacl_io/dbgprint.h"
#include "nacl_io/host_resolver.h"
#include "nacl_io/kernel_handle.h"
#include "nacl_io/kernel_wrap_real.h"
@@ -45,7 +47,8 @@
namespace nacl_io {
-KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL) {
+KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
+ sigwinch_handler_(SIG_IGN) {
}
KernelProxy::~KernelProxy() {
@@ -710,11 +713,78 @@ int KernelProxy::tcsetattr(int fd, int optional_actions,
return 0;
}
+int KernelProxy::kill(pid_t pid, int sig) {
+ // Currently we don't even pretend that other processes exist
+ // so we can only send a signal to outselves. For kill(2)
+ // pid 0 means the current process group and -1 means all the
+ // processes we have permission to send signals to.
+ if (pid != getpid() && pid != -1 && pid != 0) {
+ errno = ESRCH;
+ return -1;
+ }
+
+ dbgprintf("raising event ...\n");
+ // Raise an event so that select/poll get interrupted.
+ RaiseEvent(POLLERR);
+ switch (sig) {
+ case SIGWINCH:
+ if (sigwinch_handler_ != SIG_IGN)
+ sigwinch_handler_(SIGWINCH);
+ break;
+
+ case SIGUSR1:
+ case SIGUSR2:
+ break;
+
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
+}
+
+sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) {
+ switch (signum) {
+ // Handled signals.
+ case SIGWINCH: {
+ sighandler_t old_value = sigwinch_handler_;
+ if (handler == SIG_DFL)
+ handler = SIG_IGN;
+ sigwinch_handler_ = handler;
+ return old_value;
+ }
+
+ // Known signals
+ case SIGHUP:
+ case SIGINT:
+ case SIGKILL:
+ case SIGPIPE:
+ case SIGPOLL:
+ case SIGPROF:
+ case SIGTERM:
+ case SIGCHLD:
+ case SIGURG:
+ case SIGFPE:
+ case SIGILL:
+ case SIGQUIT:
+ case SIGSEGV:
+ case SIGTRAP:
+ if (handler == SIG_DFL)
+ return SIG_DFL;
+ break;
+ }
+
+ errno = EINVAL;
+ return SIG_ERR;
+}
+
#ifdef PROVIDES_SOCKET_API
int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
fd_set* exceptfds, struct timeval* timeout) {
ScopedEventListener listener(new EventListener);
+
std::vector<struct pollfd> fds;
fd_set readout, writeout, exceptout;
@@ -800,9 +870,24 @@ int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
ms_timeout = static_cast<int>(ms);
}
+ // Add a special node to listen for events
+ // coming from the KernelProxy itself (kill will
+ // generated a SIGERR event).
+ listener->Track(-1, ScopedKernelProxy(this), POLLERR, -1);
binji 2013/08/22 18:09:36 OK, I see why you want to use the kernel proxy for
Sam Clegg 2013/08/22 19:52:25 Done.
+ event_track += 1;
+
events.resize(event_track);
+
+ bool interrupted = false;
listener->Wait(events.data(), event_track, ms_timeout, &ready_cnt);
for (fd = 0; static_cast<int>(fd) < ready_cnt; fd++) {
+ if (events[fd].user_data == static_cast<uint64_t>(-1)) {
+ if (events[fd].events & POLLERR) {
+ interrupted = true;
+ }
+ continue;
+ }
+
if (events[fd].events & POLLIN) {
FD_SET(events[fd].user_data, &readout);
event_cnt++;
@@ -818,6 +903,11 @@ int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
event_cnt++;
}
}
+
+ if (0 == event_cnt && interrupted) {
+ errno = EINTR;
+ return -1;
+ }
}
// Copy out the results
@@ -835,10 +925,11 @@ int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
ScopedEventListener listener(new EventListener);
+ listener->Track(-1, ScopedKernelProxy(this), POLLERR, 0);
int index;
size_t event_cnt = 0;
- size_t event_track = 0;
+ size_t event_track = 1;
for (index = 0; static_cast<nfds_t>(index) < nfds; index++) {
ScopedKernelHandle handle;
struct pollfd* info = &fds[index];
@@ -873,14 +964,23 @@ int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
std::vector<EventData> events;
int ready_cnt;
+ bool interrupted = false;
events.resize(event_track);
listener->Wait(events.data(), event_track, timeout, &ready_cnt);
for (index = 0; index < ready_cnt; index++) {
struct pollfd* info = &fds[events[index].user_data];
+ if (!info) {
+ interrupted = true;
+ continue;
+ }
info->revents = events[index].events;
event_cnt++;
}
+ if (0 == event_cnt && interrupted) {
+ errno = EINTR;
+ return -1;
+ }
}
return event_cnt;

Powered by Google App Engine
This is Rietveld 408576698