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

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: 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 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 dbgprintf("raising event ...\n");
750 // Raise an event so that select/poll get interrupted.
751 static_cast<SignalEmitter&>(*signal_emitter_).SignalOccurred();
752 switch (sig) {
753 case SIGWINCH:
754 if (sigwinch_handler_ != SIG_IGN)
755 sigwinch_handler_(SIGWINCH);
756 break;
757
758 case SIGUSR1:
759 case SIGUSR2:
760 break;
761
762 default:
763 errno = EINVAL;
764 return -1;
765 }
766
767 return 0;
717 } 768 }
718 769
719 sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) { 770 sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) {
771 switch (signum) {
772 // Handled signals.
773 case SIGWINCH: {
774 sighandler_t old_value = sigwinch_handler_;
775 if (handler == SIG_DFL)
776 handler = SIG_IGN;
777 sigwinch_handler_ = handler;
778 return old_value;
779 }
780
781 // Known signals
782 case SIGHUP:
783 case SIGINT:
784 case SIGKILL:
785 case SIGPIPE:
786 case SIGPOLL:
787 case SIGPROF:
788 case SIGTERM:
789 case SIGCHLD:
790 case SIGURG:
791 case SIGFPE:
792 case SIGILL:
793 case SIGQUIT:
794 case SIGSEGV:
795 case SIGTRAP:
796 if (handler == SIG_DFL)
797 return SIG_DFL;
798 break;
799 }
800
720 errno = EINVAL; 801 errno = EINVAL;
721 return SIG_ERR; 802 return SIG_ERR;
722 } 803 }
723 804
724 #ifdef PROVIDES_SOCKET_API 805 #ifdef PROVIDES_SOCKET_API
725 806
726 int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds, 807 int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
727 fd_set* exceptfds, struct timeval* timeout) { 808 fd_set* exceptfds, struct timeval* timeout) {
728 ScopedEventListener listener(new EventListener); 809 ScopedEventListener listener(new EventListener);
810
729 std::vector<struct pollfd> fds; 811 std::vector<struct pollfd> fds;
730 812
731 fd_set readout, writeout, exceptout; 813 fd_set readout, writeout, exceptout;
732 814
733 FD_ZERO(&readout); 815 FD_ZERO(&readout);
734 FD_ZERO(&writeout); 816 FD_ZERO(&writeout);
735 FD_ZERO(&exceptout); 817 FD_ZERO(&exceptout);
736 818
737 int fd; 819 int fd;
738 size_t event_cnt = 0; 820 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)) || 886 if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
805 (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || 887 (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) ||
806 (ms < 0) || (ms >= INT_MAX)) { 888 (ms < 0) || (ms >= INT_MAX)) {
807 errno = EINVAL; 889 errno = EINVAL;
808 return -1; 890 return -1;
809 } 891 }
810 892
811 ms_timeout = static_cast<int>(ms); 893 ms_timeout = static_cast<int>(ms);
812 } 894 }
813 895
896 // Add a special node to listen for events
897 // coming from the KernelProxy itself (kill will
898 // generated a SIGERR event).
899 listener->Track(-1, signal_emitter_, POLLERR, -1);
900 event_track += 1;
901
814 events.resize(event_track); 902 events.resize(event_track);
903
904 bool interrupted = false;
815 listener->Wait(events.data(), event_track, ms_timeout, &ready_cnt); 905 listener->Wait(events.data(), event_track, ms_timeout, &ready_cnt);
816 for (fd = 0; static_cast<int>(fd) < ready_cnt; fd++) { 906 for (fd = 0; static_cast<int>(fd) < ready_cnt; fd++) {
907 if (events[fd].user_data == static_cast<uint64_t>(-1)) {
908 if (events[fd].events & POLLERR) {
909 interrupted = true;
910 }
911 continue;
912 }
913
817 if (events[fd].events & POLLIN) { 914 if (events[fd].events & POLLIN) {
818 FD_SET(events[fd].user_data, &readout); 915 FD_SET(events[fd].user_data, &readout);
819 event_cnt++; 916 event_cnt++;
820 } 917 }
821 918
822 if (events[fd].events & POLLOUT) { 919 if (events[fd].events & POLLOUT) {
823 FD_SET(events[fd].user_data, &writeout); 920 FD_SET(events[fd].user_data, &writeout);
824 event_cnt++; 921 event_cnt++;
825 } 922 }
826 923
827 if (events[fd].events & (POLLERR | POLLHUP)) { 924 if (events[fd].events & (POLLERR | POLLHUP)) {
828 FD_SET(events[fd].user_data, &exceptout); 925 FD_SET(events[fd].user_data, &exceptout);
829 event_cnt++; 926 event_cnt++;
830 } 927 }
831 } 928 }
929
930 if (0 == event_cnt && interrupted) {
931 errno = EINTR;
932 return -1;
933 }
832 } 934 }
833 935
834 // Copy out the results 936 // Copy out the results
835 if (readfds != NULL) 937 if (readfds != NULL)
836 *readfds = readout; 938 *readfds = readout;
837 939
838 if (writefds != NULL) 940 if (writefds != NULL)
839 *writefds = writeout; 941 *writefds = writeout;
840 942
841 if (exceptfds != NULL) 943 if (exceptfds != NULL)
842 *exceptfds = exceptout; 944 *exceptfds = exceptout;
843 945
844 return event_cnt; 946 return event_cnt;
845 } 947 }
846 948
847 int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) { 949 int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
848 ScopedEventListener listener(new EventListener); 950 ScopedEventListener listener(new EventListener);
951 listener->Track(-1, signal_emitter_, POLLERR, 0);
849 952
850 int index; 953 int index;
851 size_t event_cnt = 0; 954 size_t event_cnt = 0;
852 size_t event_track = 0; 955 size_t event_track = 1;
853 for (index = 0; static_cast<nfds_t>(index) < nfds; index++) { 956 for (index = 0; static_cast<nfds_t>(index) < nfds; index++) {
854 ScopedKernelHandle handle; 957 ScopedKernelHandle handle;
855 struct pollfd* info = &fds[index]; 958 struct pollfd* info = &fds[index];
856 Error err = AcquireHandle(info->fd, &handle); 959 Error err = AcquireHandle(info->fd, &handle);
857 960
858 // If the node isn't open, or somehow invalid, mark it so. 961 // If the node isn't open, or somehow invalid, mark it so.
859 if (err != 0) { 962 if (err != 0) {
860 info->revents = POLLNVAL; 963 info->revents = POLLNVAL;
861 event_cnt++; 964 event_cnt++;
862 continue; 965 continue;
(...skipping 14 matching lines...) Expand all
877 continue; 980 continue;
878 } 981 }
879 event_track++; 982 event_track++;
880 } 983 }
881 984
882 // If nothing is signaled, then we must wait. 985 // If nothing is signaled, then we must wait.
883 if (0 == event_cnt) { 986 if (0 == event_cnt) {
884 std::vector<EventData> events; 987 std::vector<EventData> events;
885 int ready_cnt; 988 int ready_cnt;
886 989
990 bool interrupted = false;
887 events.resize(event_track); 991 events.resize(event_track);
888 listener->Wait(events.data(), event_track, timeout, &ready_cnt); 992 listener->Wait(events.data(), event_track, timeout, &ready_cnt);
889 for (index = 0; index < ready_cnt; index++) { 993 for (index = 0; index < ready_cnt; index++) {
890 struct pollfd* info = &fds[events[index].user_data]; 994 struct pollfd* info = &fds[events[index].user_data];
995 if (!info) {
996 interrupted = true;
997 continue;
998 }
891 999
892 info->revents = events[index].events; 1000 info->revents = events[index].events;
893 event_cnt++; 1001 event_cnt++;
894 } 1002 }
1003 if (0 == event_cnt && interrupted) {
1004 errno = EINTR;
1005 return -1;
1006 }
895 } 1007 }
896 1008
897 return event_cnt; 1009 return event_cnt;
898 } 1010 }
899 1011
900 1012
901 1013
902 // Socket Functions 1014 // Socket Functions
903 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) { 1015 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
904 if (NULL == addr || NULL == len) { 1016 if (NULL == addr || NULL == len) {
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
1257 errno = ENOTSOCK; 1369 errno = ENOTSOCK;
1258 return -1; 1370 return -1;
1259 } 1371 }
1260 1372
1261 return 0; 1373 return 0;
1262 } 1374 }
1263 1375
1264 #endif // PROVIDES_SOCKET_API 1376 #endif // PROVIDES_SOCKET_API
1265 1377
1266 } // namespace_nacl_io 1378 } // namespace_nacl_io
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698