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

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: nits 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 49cf86dfe1172ebb56a3ef7dc20fc29343a218e6..84e531e8fa439ce602ff7e43870e1f9ee12f4e55 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -19,6 +19,7 @@
#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"
@@ -46,7 +47,31 @@
namespace nacl_io {
-KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL) {
+class SignalEmitter : public EventEmitter {
+ public:
+ // From EventEmitter. The SignalEmitter exists in order
+ // to inturrupt anything waiting in select()/poll() when kill()
+ // is called. It is an edge trigger only and therefore has no
+ // persistent readable/wriable/error state.
+ uint32_t GetEventStatus() {
+ return 0;
+ }
+
+ int GetType() {
+ // For lack of a better type, report socket to signify it can be in an
+ // used to signal.
+ return S_IFSOCK;
+ }
+
+ void SignalOccurred() {
+ RaiseEvent(POLLERR);
+ }
+};
+
+KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
+ sigwinch_handler_(SIG_IGN),
+ signal_emitter_(new SignalEmitter) {
+
}
KernelProxy::~KernelProxy() {
@@ -712,11 +737,66 @@ int KernelProxy::tcsetattr(int fd, int optional_actions,
}
int KernelProxy::kill(pid_t pid, int sig) {
- errno = EINVAL;
- return -1;
+ // 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;
+ }
+
+ // Raise an event so that select/poll get interrupted.
+ signal_emitter_->SignalOccurred();
+ 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;
}
@@ -726,6 +806,7 @@ sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) {
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;
@@ -811,9 +892,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, signal_emitter_, POLLERR, -1);
+ 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++;
@@ -829,6 +925,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
@@ -846,10 +947,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, signal_emitter_, 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];
@@ -884,14 +986,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;
« no previous file with comments | « native_client_sdk/src/libraries/nacl_io/kernel_proxy.h ('k') | native_client_sdk/src/libraries/nacl_io/mount_node_tty.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698