Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 | 18 |
| 18 #include <iterator> | 19 #include <iterator> |
| 19 #include <string> | 20 #include <string> |
| 20 | 21 |
| 22 #include "nacl_io/dbgprint.h" | |
| 21 #include "nacl_io/host_resolver.h" | 23 #include "nacl_io/host_resolver.h" |
| 22 #include "nacl_io/kernel_handle.h" | 24 #include "nacl_io/kernel_handle.h" |
| 23 #include "nacl_io/kernel_wrap_real.h" | 25 #include "nacl_io/kernel_wrap_real.h" |
| 24 #include "nacl_io/mount.h" | 26 #include "nacl_io/mount.h" |
| 25 #include "nacl_io/mount_dev.h" | 27 #include "nacl_io/mount_dev.h" |
| 26 #include "nacl_io/mount_html5fs.h" | 28 #include "nacl_io/mount_html5fs.h" |
| 27 #include "nacl_io/mount_http.h" | 29 #include "nacl_io/mount_http.h" |
| 28 #include "nacl_io/mount_mem.h" | 30 #include "nacl_io/mount_mem.h" |
| 29 #include "nacl_io/mount_node.h" | 31 #include "nacl_io/mount_node.h" |
| 30 #include "nacl_io/mount_node_tcp.h" | 32 #include "nacl_io/mount_node_tcp.h" |
| 31 #include "nacl_io/mount_node_udp.h" | 33 #include "nacl_io/mount_node_udp.h" |
| 32 #include "nacl_io/mount_passthrough.h" | 34 #include "nacl_io/mount_passthrough.h" |
| 33 #include "nacl_io/osmman.h" | 35 #include "nacl_io/osmman.h" |
| 34 #include "nacl_io/ossocket.h" | 36 #include "nacl_io/ossocket.h" |
| 35 #include "nacl_io/osstat.h" | 37 #include "nacl_io/osstat.h" |
| 36 #include "nacl_io/path.h" | 38 #include "nacl_io/path.h" |
| 37 #include "nacl_io/pepper_interface.h" | 39 #include "nacl_io/pepper_interface.h" |
| 38 #include "nacl_io/typed_mount_factory.h" | 40 #include "nacl_io/typed_mount_factory.h" |
| 39 #include "sdk_util/auto_lock.h" | 41 #include "sdk_util/auto_lock.h" |
| 40 #include "sdk_util/ref_object.h" | 42 #include "sdk_util/ref_object.h" |
| 41 | 43 |
| 42 #ifndef MAXPATHLEN | 44 #ifndef MAXPATHLEN |
| 43 #define MAXPATHLEN 256 | 45 #define MAXPATHLEN 256 |
| 44 #endif | 46 #endif |
| 45 | 47 |
| 46 namespace nacl_io { | 48 namespace nacl_io { |
| 47 | 49 |
| 48 KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL) { | 50 KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL), |
| 51 sigwinch_handler_(SIG_IGN) { | |
| 49 } | 52 } |
| 50 | 53 |
| 51 KernelProxy::~KernelProxy() { | 54 KernelProxy::~KernelProxy() { |
| 52 // Clean up the MountFactories. | 55 // Clean up the MountFactories. |
| 53 for (MountFactoryMap_t::iterator i = factories_.begin(); | 56 for (MountFactoryMap_t::iterator i = factories_.begin(); |
| 54 i != factories_.end(); | 57 i != factories_.end(); |
| 55 ++i) { | 58 ++i) { |
| 56 delete i->second; | 59 delete i->second; |
| 57 } | 60 } |
| 58 | 61 |
| (...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 703 | 706 |
| 704 error = handle->node()->Tcsetattr(optional_actions, termios_p); | 707 error = handle->node()->Tcsetattr(optional_actions, termios_p); |
| 705 if (error) { | 708 if (error) { |
| 706 errno = error; | 709 errno = error; |
| 707 return -1; | 710 return -1; |
| 708 } | 711 } |
| 709 | 712 |
| 710 return 0; | 713 return 0; |
| 711 } | 714 } |
| 712 | 715 |
| 716 int KernelProxy::kill(pid_t pid, int sig) { | |
| 717 // Currently we don't even pretend that other processes exist | |
| 718 // so we can only send a signal to outselves. For kill(2) | |
| 719 // pid 0 means the current process group and -1 means all the | |
| 720 // processes we have permission to send signals to. | |
| 721 if (pid != getpid() && pid != -1 && pid != 0) { | |
| 722 errno = ESRCH; | |
| 723 return -1; | |
| 724 } | |
| 725 | |
| 726 dbgprintf("raising event ...\n"); | |
| 727 // Raise an event so that select/poll get interrupted. | |
| 728 RaiseEvent(POLLERR); | |
| 729 switch (sig) { | |
| 730 case SIGWINCH: | |
| 731 if (sigwinch_handler_ != SIG_IGN) | |
| 732 sigwinch_handler_(SIGWINCH); | |
| 733 break; | |
| 734 | |
| 735 case SIGUSR1: | |
| 736 case SIGUSR2: | |
| 737 break; | |
| 738 | |
| 739 default: | |
| 740 errno = EINVAL; | |
| 741 return -1; | |
| 742 } | |
| 743 | |
| 744 return 0; | |
| 745 } | |
| 746 | |
| 747 sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) { | |
| 748 switch (signum) { | |
| 749 // Handled signals. | |
| 750 case SIGWINCH: { | |
| 751 sighandler_t old_value = sigwinch_handler_; | |
| 752 if (handler == SIG_DFL) | |
| 753 handler = SIG_IGN; | |
| 754 sigwinch_handler_ = handler; | |
| 755 return old_value; | |
| 756 } | |
| 757 | |
| 758 // Known signals | |
| 759 case SIGHUP: | |
| 760 case SIGINT: | |
| 761 case SIGKILL: | |
| 762 case SIGPIPE: | |
| 763 case SIGPOLL: | |
| 764 case SIGPROF: | |
| 765 case SIGTERM: | |
| 766 case SIGCHLD: | |
| 767 case SIGURG: | |
| 768 case SIGFPE: | |
| 769 case SIGILL: | |
| 770 case SIGQUIT: | |
| 771 case SIGSEGV: | |
| 772 case SIGTRAP: | |
| 773 if (handler == SIG_DFL) | |
| 774 return SIG_DFL; | |
| 775 break; | |
| 776 } | |
| 777 | |
| 778 errno = EINVAL; | |
| 779 return SIG_ERR; | |
| 780 } | |
| 781 | |
| 713 #ifdef PROVIDES_SOCKET_API | 782 #ifdef PROVIDES_SOCKET_API |
| 714 | 783 |
| 715 int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds, | 784 int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds, |
| 716 fd_set* exceptfds, struct timeval* timeout) { | 785 fd_set* exceptfds, struct timeval* timeout) { |
| 717 ScopedEventListener listener(new EventListener); | 786 ScopedEventListener listener(new EventListener); |
| 787 | |
| 718 std::vector<struct pollfd> fds; | 788 std::vector<struct pollfd> fds; |
| 719 | 789 |
| 720 fd_set readout, writeout, exceptout; | 790 fd_set readout, writeout, exceptout; |
| 721 | 791 |
| 722 FD_ZERO(&readout); | 792 FD_ZERO(&readout); |
| 723 FD_ZERO(&writeout); | 793 FD_ZERO(&writeout); |
| 724 FD_ZERO(&exceptout); | 794 FD_ZERO(&exceptout); |
| 725 | 795 |
| 726 int fd; | 796 int fd; |
| 727 size_t event_cnt = 0; | 797 size_t event_cnt = 0; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 793 if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) || | 863 if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) || |
| 794 (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || | 864 (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || |
| 795 (ms < 0) || (ms >= INT_MAX)) { | 865 (ms < 0) || (ms >= INT_MAX)) { |
| 796 errno = EINVAL; | 866 errno = EINVAL; |
| 797 return -1; | 867 return -1; |
| 798 } | 868 } |
| 799 | 869 |
| 800 ms_timeout = static_cast<int>(ms); | 870 ms_timeout = static_cast<int>(ms); |
| 801 } | 871 } |
| 802 | 872 |
| 873 // Add a special node to listen for events | |
| 874 // coming from the KernelProxy itself (kill will | |
| 875 // generated a SIGERR event). | |
| 876 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.
| |
| 877 event_track += 1; | |
| 878 | |
| 803 events.resize(event_track); | 879 events.resize(event_track); |
| 880 | |
| 881 bool interrupted = false; | |
| 804 listener->Wait(events.data(), event_track, ms_timeout, &ready_cnt); | 882 listener->Wait(events.data(), event_track, ms_timeout, &ready_cnt); |
| 805 for (fd = 0; static_cast<int>(fd) < ready_cnt; fd++) { | 883 for (fd = 0; static_cast<int>(fd) < ready_cnt; fd++) { |
| 884 if (events[fd].user_data == static_cast<uint64_t>(-1)) { | |
| 885 if (events[fd].events & POLLERR) { | |
| 886 interrupted = true; | |
| 887 } | |
| 888 continue; | |
| 889 } | |
| 890 | |
| 806 if (events[fd].events & POLLIN) { | 891 if (events[fd].events & POLLIN) { |
| 807 FD_SET(events[fd].user_data, &readout); | 892 FD_SET(events[fd].user_data, &readout); |
| 808 event_cnt++; | 893 event_cnt++; |
| 809 } | 894 } |
| 810 | 895 |
| 811 if (events[fd].events & POLLOUT) { | 896 if (events[fd].events & POLLOUT) { |
| 812 FD_SET(events[fd].user_data, &writeout); | 897 FD_SET(events[fd].user_data, &writeout); |
| 813 event_cnt++; | 898 event_cnt++; |
| 814 } | 899 } |
| 815 | 900 |
| 816 if (events[fd].events & (POLLERR | POLLHUP)) { | 901 if (events[fd].events & (POLLERR | POLLHUP)) { |
| 817 FD_SET(events[fd].user_data, &exceptout); | 902 FD_SET(events[fd].user_data, &exceptout); |
| 818 event_cnt++; | 903 event_cnt++; |
| 819 } | 904 } |
| 820 } | 905 } |
| 906 | |
| 907 if (0 == event_cnt && interrupted) { | |
| 908 errno = EINTR; | |
| 909 return -1; | |
| 910 } | |
| 821 } | 911 } |
| 822 | 912 |
| 823 // Copy out the results | 913 // Copy out the results |
| 824 if (readfds != NULL) | 914 if (readfds != NULL) |
| 825 *readfds = readout; | 915 *readfds = readout; |
| 826 | 916 |
| 827 if (writefds != NULL) | 917 if (writefds != NULL) |
| 828 *writefds = writeout; | 918 *writefds = writeout; |
| 829 | 919 |
| 830 if (exceptfds != NULL) | 920 if (exceptfds != NULL) |
| 831 *exceptfds = exceptout; | 921 *exceptfds = exceptout; |
| 832 | 922 |
| 833 return event_cnt; | 923 return event_cnt; |
| 834 } | 924 } |
| 835 | 925 |
| 836 int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) { | 926 int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) { |
| 837 ScopedEventListener listener(new EventListener); | 927 ScopedEventListener listener(new EventListener); |
| 928 listener->Track(-1, ScopedKernelProxy(this), POLLERR, 0); | |
| 838 | 929 |
| 839 int index; | 930 int index; |
| 840 size_t event_cnt = 0; | 931 size_t event_cnt = 0; |
| 841 size_t event_track = 0; | 932 size_t event_track = 1; |
| 842 for (index = 0; static_cast<nfds_t>(index) < nfds; index++) { | 933 for (index = 0; static_cast<nfds_t>(index) < nfds; index++) { |
| 843 ScopedKernelHandle handle; | 934 ScopedKernelHandle handle; |
| 844 struct pollfd* info = &fds[index]; | 935 struct pollfd* info = &fds[index]; |
| 845 Error err = AcquireHandle(info->fd, &handle); | 936 Error err = AcquireHandle(info->fd, &handle); |
| 846 | 937 |
| 847 // If the node isn't open, or somehow invalid, mark it so. | 938 // If the node isn't open, or somehow invalid, mark it so. |
| 848 if (err != 0) { | 939 if (err != 0) { |
| 849 info->revents = POLLNVAL; | 940 info->revents = POLLNVAL; |
| 850 event_cnt++; | 941 event_cnt++; |
| 851 continue; | 942 continue; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 866 continue; | 957 continue; |
| 867 } | 958 } |
| 868 event_track++; | 959 event_track++; |
| 869 } | 960 } |
| 870 | 961 |
| 871 // If nothing is signaled, then we must wait. | 962 // If nothing is signaled, then we must wait. |
| 872 if (0 == event_cnt) { | 963 if (0 == event_cnt) { |
| 873 std::vector<EventData> events; | 964 std::vector<EventData> events; |
| 874 int ready_cnt; | 965 int ready_cnt; |
| 875 | 966 |
| 967 bool interrupted = false; | |
| 876 events.resize(event_track); | 968 events.resize(event_track); |
| 877 listener->Wait(events.data(), event_track, timeout, &ready_cnt); | 969 listener->Wait(events.data(), event_track, timeout, &ready_cnt); |
| 878 for (index = 0; index < ready_cnt; index++) { | 970 for (index = 0; index < ready_cnt; index++) { |
| 879 struct pollfd* info = &fds[events[index].user_data]; | 971 struct pollfd* info = &fds[events[index].user_data]; |
| 972 if (!info) { | |
| 973 interrupted = true; | |
| 974 continue; | |
| 975 } | |
| 880 | 976 |
| 881 info->revents = events[index].events; | 977 info->revents = events[index].events; |
| 882 event_cnt++; | 978 event_cnt++; |
| 883 } | 979 } |
| 980 if (0 == event_cnt && interrupted) { | |
| 981 errno = EINTR; | |
| 982 return -1; | |
| 983 } | |
| 884 } | 984 } |
| 885 | 985 |
| 886 return event_cnt; | 986 return event_cnt; |
| 887 } | 987 } |
| 888 | 988 |
| 889 | 989 |
| 890 | 990 |
| 891 // Socket Functions | 991 // Socket Functions |
| 892 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) { | 992 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) { |
| 893 if (NULL == addr || NULL == len) { | 993 if (NULL == addr || NULL == len) { |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1246 errno = ENOTSOCK; | 1346 errno = ENOTSOCK; |
| 1247 return -1; | 1347 return -1; |
| 1248 } | 1348 } |
| 1249 | 1349 |
| 1250 return 0; | 1350 return 0; |
| 1251 } | 1351 } |
| 1252 | 1352 |
| 1253 #endif // PROVIDES_SOCKET_API | 1353 #endif // PROVIDES_SOCKET_API |
| 1254 | 1354 |
| 1255 } // namespace_nacl_io | 1355 } // namespace_nacl_io |
| OLD | NEW |