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

Side by Side 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, 3 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "nacl_io/kernel_proxy.h" 5 #include "nacl_io/kernel_proxy.h"
6 6
7 7
8 #include <assert.h> 8 #include <assert.h>
9 #include <errno.h> 9 #include <errno.h>
10 #include <fcntl.h> 10 #include <fcntl.h>
11 #include <limits.h> 11 #include <limits.h>
12 #include <poll.h> 12 #include <poll.h>
13 #include <pthread.h> 13 #include <pthread.h>
14 #include <stdio.h> 14 #include <stdio.h>
15 #include <string.h> 15 #include <string.h>
16 #include <sys/time.h> 16 #include <sys/time.h>
17 #include <unistd.h> 17 #include <unistd.h>
18 18
19 #include <iterator> 19 #include <iterator>
20 #include <string> 20 #include <string>
21 21
22 #include "nacl_io/dbgprint.h"
22 #include "nacl_io/host_resolver.h" 23 #include "nacl_io/host_resolver.h"
23 #include "nacl_io/kernel_handle.h" 24 #include "nacl_io/kernel_handle.h"
24 #include "nacl_io/kernel_wrap_real.h" 25 #include "nacl_io/kernel_wrap_real.h"
25 #include "nacl_io/mount.h" 26 #include "nacl_io/mount.h"
26 #include "nacl_io/mount_dev.h" 27 #include "nacl_io/mount_dev.h"
27 #include "nacl_io/mount_html5fs.h" 28 #include "nacl_io/mount_html5fs.h"
28 #include "nacl_io/mount_http.h" 29 #include "nacl_io/mount_http.h"
29 #include "nacl_io/mount_mem.h" 30 #include "nacl_io/mount_mem.h"
30 #include "nacl_io/mount_node.h" 31 #include "nacl_io/mount_node.h"
31 #include "nacl_io/mount_node_tcp.h" 32 #include "nacl_io/mount_node_tcp.h"
32 #include "nacl_io/mount_node_udp.h" 33 #include "nacl_io/mount_node_udp.h"
33 #include "nacl_io/mount_passthrough.h" 34 #include "nacl_io/mount_passthrough.h"
34 #include "nacl_io/osmman.h" 35 #include "nacl_io/osmman.h"
35 #include "nacl_io/ossocket.h" 36 #include "nacl_io/ossocket.h"
36 #include "nacl_io/osstat.h" 37 #include "nacl_io/osstat.h"
37 #include "nacl_io/path.h" 38 #include "nacl_io/path.h"
38 #include "nacl_io/pepper_interface.h" 39 #include "nacl_io/pepper_interface.h"
39 #include "nacl_io/typed_mount_factory.h" 40 #include "nacl_io/typed_mount_factory.h"
40 #include "sdk_util/auto_lock.h" 41 #include "sdk_util/auto_lock.h"
41 #include "sdk_util/ref_object.h" 42 #include "sdk_util/ref_object.h"
42 43
43 #ifndef MAXPATHLEN 44 #ifndef MAXPATHLEN
44 #define MAXPATHLEN 256 45 #define MAXPATHLEN 256
45 #endif 46 #endif
46 47
47 namespace nacl_io { 48 namespace nacl_io {
48 49
49 KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL) { 50 class SignalEmitter : public EventEmitter {
51 public:
52 // From EventEmitter. The SignalEmitter exists in order
53 // to inturrupt anything waiting in select()/poll() when kill()
54 // is called. It is an edge trigger only and therefore has no
55 // persistent readable/wriable/error state.
56 uint32_t GetEventStatus() {
57 return 0;
58 }
59
60 int GetType() {
61 // For lack of a better type, report socket to signify it can be in an
62 // used to signal.
63 return S_IFSOCK;
64 }
65
66 void SignalOccurred() {
67 RaiseEvent(POLLERR);
68 }
69 };
70
71 KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
72 sigwinch_handler_(SIG_IGN),
73 signal_emitter_(new SignalEmitter) {
74
50 } 75 }
51 76
52 KernelProxy::~KernelProxy() { 77 KernelProxy::~KernelProxy() {
53 // Clean up the MountFactories. 78 // Clean up the MountFactories.
54 for (MountFactoryMap_t::iterator i = factories_.begin(); 79 for (MountFactoryMap_t::iterator i = factories_.begin();
55 i != factories_.end(); 80 i != factories_.end();
56 ++i) { 81 ++i) {
57 delete i->second; 82 delete i->second;
58 } 83 }
59 84
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 error = handle->node()->Tcsetattr(optional_actions, termios_p); 730 error = handle->node()->Tcsetattr(optional_actions, termios_p);
706 if (error) { 731 if (error) {
707 errno = error; 732 errno = error;
708 return -1; 733 return -1;
709 } 734 }
710 735
711 return 0; 736 return 0;
712 } 737 }
713 738
714 int KernelProxy::kill(pid_t pid, int sig) { 739 int KernelProxy::kill(pid_t pid, int sig) {
715 errno = EINVAL; 740 // Currently we don't even pretend that other processes exist
716 return -1; 741 // so we can only send a signal to outselves. For kill(2)
742 // pid 0 means the current process group and -1 means all the
743 // processes we have permission to send signals to.
744 if (pid != getpid() && pid != -1 && pid != 0) {
745 errno = ESRCH;
746 return -1;
747 }
748
749 // Raise an event so that select/poll get interrupted.
750 signal_emitter_->SignalOccurred();
751 switch (sig) {
752 case SIGWINCH:
753 if (sigwinch_handler_ != SIG_IGN)
754 sigwinch_handler_(SIGWINCH);
755 break;
756
757 case SIGUSR1:
758 case SIGUSR2:
759 break;
760
761 default:
762 errno = EINVAL;
763 return -1;
764 }
765
766 return 0;
717 } 767 }
718 768
719 sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) { 769 sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) {
770 switch (signum) {
771 // Handled signals.
772 case SIGWINCH: {
773 sighandler_t old_value = sigwinch_handler_;
774 if (handler == SIG_DFL)
775 handler = SIG_IGN;
776 sigwinch_handler_ = handler;
777 return old_value;
778 }
779
780 // Known signals
781 case SIGHUP:
782 case SIGINT:
783 case SIGKILL:
784 case SIGPIPE:
785 case SIGPOLL:
786 case SIGPROF:
787 case SIGTERM:
788 case SIGCHLD:
789 case SIGURG:
790 case SIGFPE:
791 case SIGILL:
792 case SIGQUIT:
793 case SIGSEGV:
794 case SIGTRAP:
795 if (handler == SIG_DFL)
796 return SIG_DFL;
797 break;
798 }
799
720 errno = EINVAL; 800 errno = EINVAL;
721 return SIG_ERR; 801 return SIG_ERR;
722 } 802 }
723 803
724 #ifdef PROVIDES_SOCKET_API 804 #ifdef PROVIDES_SOCKET_API
725 805
726 int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds, 806 int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
727 fd_set* exceptfds, struct timeval* timeout) { 807 fd_set* exceptfds, struct timeval* timeout) {
728 ScopedEventListener listener(new EventListener); 808 ScopedEventListener listener(new EventListener);
809
729 std::vector<struct pollfd> fds; 810 std::vector<struct pollfd> fds;
730 811
731 fd_set readout, writeout, exceptout; 812 fd_set readout, writeout, exceptout;
732 813
733 FD_ZERO(&readout); 814 FD_ZERO(&readout);
734 FD_ZERO(&writeout); 815 FD_ZERO(&writeout);
735 FD_ZERO(&exceptout); 816 FD_ZERO(&exceptout);
736 817
737 int fd; 818 int fd;
738 size_t event_cnt = 0; 819 size_t event_cnt = 0;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) || 885 if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
805 (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || 886 (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) ||
806 (ms < 0) || (ms >= INT_MAX)) { 887 (ms < 0) || (ms >= INT_MAX)) {
807 errno = EINVAL; 888 errno = EINVAL;
808 return -1; 889 return -1;
809 } 890 }
810 891
811 ms_timeout = static_cast<int>(ms); 892 ms_timeout = static_cast<int>(ms);
812 } 893 }
813 894
895 // Add a special node to listen for events
896 // coming from the KernelProxy itself (kill will
897 // generated a SIGERR event).
898 listener->Track(-1, signal_emitter_, POLLERR, -1);
899 event_track += 1;
900
814 events.resize(event_track); 901 events.resize(event_track);
902
903 bool interrupted = false;
815 listener->Wait(events.data(), event_track, ms_timeout, &ready_cnt); 904 listener->Wait(events.data(), event_track, ms_timeout, &ready_cnt);
816 for (fd = 0; static_cast<int>(fd) < ready_cnt; fd++) { 905 for (fd = 0; static_cast<int>(fd) < ready_cnt; fd++) {
906 if (events[fd].user_data == static_cast<uint64_t>(-1)) {
907 if (events[fd].events & POLLERR) {
908 interrupted = true;
909 }
910 continue;
911 }
912
817 if (events[fd].events & POLLIN) { 913 if (events[fd].events & POLLIN) {
818 FD_SET(events[fd].user_data, &readout); 914 FD_SET(events[fd].user_data, &readout);
819 event_cnt++; 915 event_cnt++;
820 } 916 }
821 917
822 if (events[fd].events & POLLOUT) { 918 if (events[fd].events & POLLOUT) {
823 FD_SET(events[fd].user_data, &writeout); 919 FD_SET(events[fd].user_data, &writeout);
824 event_cnt++; 920 event_cnt++;
825 } 921 }
826 922
827 if (events[fd].events & (POLLERR | POLLHUP)) { 923 if (events[fd].events & (POLLERR | POLLHUP)) {
828 FD_SET(events[fd].user_data, &exceptout); 924 FD_SET(events[fd].user_data, &exceptout);
829 event_cnt++; 925 event_cnt++;
830 } 926 }
831 } 927 }
928
929 if (0 == event_cnt && interrupted) {
930 errno = EINTR;
931 return -1;
932 }
832 } 933 }
833 934
834 // Copy out the results 935 // Copy out the results
835 if (readfds != NULL) 936 if (readfds != NULL)
836 *readfds = readout; 937 *readfds = readout;
837 938
838 if (writefds != NULL) 939 if (writefds != NULL)
839 *writefds = writeout; 940 *writefds = writeout;
840 941
841 if (exceptfds != NULL) 942 if (exceptfds != NULL)
842 *exceptfds = exceptout; 943 *exceptfds = exceptout;
843 944
844 return event_cnt; 945 return event_cnt;
845 } 946 }
846 947
847 int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) { 948 int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
848 ScopedEventListener listener(new EventListener); 949 ScopedEventListener listener(new EventListener);
950 listener->Track(-1, signal_emitter_, POLLERR, 0);
849 951
850 int index; 952 int index;
851 size_t event_cnt = 0; 953 size_t event_cnt = 0;
852 size_t event_track = 0; 954 size_t event_track = 1;
853 for (index = 0; static_cast<nfds_t>(index) < nfds; index++) { 955 for (index = 0; static_cast<nfds_t>(index) < nfds; index++) {
854 ScopedKernelHandle handle; 956 ScopedKernelHandle handle;
855 struct pollfd* info = &fds[index]; 957 struct pollfd* info = &fds[index];
856 Error err = AcquireHandle(info->fd, &handle); 958 Error err = AcquireHandle(info->fd, &handle);
857 959
858 // If the node isn't open, or somehow invalid, mark it so. 960 // If the node isn't open, or somehow invalid, mark it so.
859 if (err != 0) { 961 if (err != 0) {
860 info->revents = POLLNVAL; 962 info->revents = POLLNVAL;
861 event_cnt++; 963 event_cnt++;
862 continue; 964 continue;
(...skipping 14 matching lines...) Expand all
877 continue; 979 continue;
878 } 980 }
879 event_track++; 981 event_track++;
880 } 982 }
881 983
882 // If nothing is signaled, then we must wait. 984 // If nothing is signaled, then we must wait.
883 if (0 == event_cnt) { 985 if (0 == event_cnt) {
884 std::vector<EventData> events; 986 std::vector<EventData> events;
885 int ready_cnt; 987 int ready_cnt;
886 988
989 bool interrupted = false;
887 events.resize(event_track); 990 events.resize(event_track);
888 listener->Wait(events.data(), event_track, timeout, &ready_cnt); 991 listener->Wait(events.data(), event_track, timeout, &ready_cnt);
889 for (index = 0; index < ready_cnt; index++) { 992 for (index = 0; index < ready_cnt; index++) {
890 struct pollfd* info = &fds[events[index].user_data]; 993 struct pollfd* info = &fds[events[index].user_data];
994 if (!info) {
995 interrupted = true;
996 continue;
997 }
891 998
892 info->revents = events[index].events; 999 info->revents = events[index].events;
893 event_cnt++; 1000 event_cnt++;
894 } 1001 }
1002 if (0 == event_cnt && interrupted) {
1003 errno = EINTR;
1004 return -1;
1005 }
895 } 1006 }
896 1007
897 return event_cnt; 1008 return event_cnt;
898 } 1009 }
899 1010
900 1011
901 1012
902 // Socket Functions 1013 // Socket Functions
903 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) { 1014 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
904 if (NULL == addr || NULL == len) { 1015 if (NULL == addr || NULL == len) {
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
1257 errno = ENOTSOCK; 1368 errno = ENOTSOCK;
1258 return -1; 1369 return -1;
1259 } 1370 }
1260 1371
1261 return 0; 1372 return 0;
1262 } 1373 }
1263 1374
1264 #endif // PROVIDES_SOCKET_API 1375 #endif // PROVIDES_SOCKET_API
1265 1376
1266 } // namespace_nacl_io 1377 } // namespace_nacl_io
OLDNEW
« 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