diff options
Diffstat (limited to 'arch/um/drivers/chan_user.c')
-rw-r--r-- | arch/um/drivers/chan_user.c | 70 |
1 files changed, 38 insertions, 32 deletions
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 5d1289d33410..8b81bd5f20f2 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c | |||
@@ -51,19 +51,21 @@ error: | |||
51 | /* | 51 | /* |
52 | * UML SIGWINCH handling | 52 | * UML SIGWINCH handling |
53 | * | 53 | * |
54 | * The point of this is to handle SIGWINCH on consoles which have host ttys and | 54 | * The point of this is to handle SIGWINCH on consoles which have host |
55 | * relay them inside UML to whatever might be running on the console and cares | 55 | * ttys and relay them inside UML to whatever might be running on the |
56 | * about the window size (since SIGWINCH notifies about terminal size changes). | 56 | * console and cares about the window size (since SIGWINCH notifies |
57 | * about terminal size changes). | ||
57 | * | 58 | * |
58 | * So, we have a separate thread for each host tty attached to a UML device | 59 | * So, we have a separate thread for each host tty attached to a UML |
59 | * (side-issue - I'm annoyed that one thread can't have multiple controlling | 60 | * device (side-issue - I'm annoyed that one thread can't have |
60 | * ttys for purposed of handling SIGWINCH, but I imagine there are other reasons | 61 | * multiple controlling ttys for the purpose of handling SIGWINCH, but |
61 | * that doesn't make any sense). | 62 | * I imagine there are other reasons that doesn't make any sense). |
62 | * | 63 | * |
63 | * SIGWINCH can't be received synchronously, so you have to set up to receive it | 64 | * SIGWINCH can't be received synchronously, so you have to set up to |
64 | * as a signal. That being the case, if you are going to wait for it, it is | 65 | * receive it as a signal. That being the case, if you are going to |
65 | * convenient to sit in sigsuspend() and wait for the signal to bounce you out of | 66 | * wait for it, it is convenient to sit in sigsuspend() and wait for |
66 | * it (see below for how we make sure to exit only on SIGWINCH). | 67 | * the signal to bounce you out of it (see below for how we make sure |
68 | * to exit only on SIGWINCH). | ||
67 | */ | 69 | */ |
68 | 70 | ||
69 | static void winch_handler(int sig) | 71 | static void winch_handler(int sig) |
@@ -112,7 +114,8 @@ static int winch_thread(void *arg) | |||
112 | 114 | ||
113 | err = os_new_tty_pgrp(pty_fd, os_getpid()); | 115 | err = os_new_tty_pgrp(pty_fd, os_getpid()); |
114 | if(err < 0){ | 116 | if(err < 0){ |
115 | printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err); | 117 | printk("winch_thread : new_tty_pgrp failed on fd %d, " |
118 | "err = %d\n", pty_fd, -err); | ||
116 | exit(1); | 119 | exit(1); |
117 | } | 120 | } |
118 | 121 | ||
@@ -126,8 +129,9 @@ static int winch_thread(void *arg) | |||
126 | "err = %d\n", -count); | 129 | "err = %d\n", -count); |
127 | 130 | ||
128 | while(1){ | 131 | while(1){ |
129 | /* This will be interrupted by SIGWINCH only, since other signals | 132 | /* This will be interrupted by SIGWINCH only, since |
130 | * are blocked.*/ | 133 | * other signals are blocked. |
134 | */ | ||
131 | sigsuspend(&sigs); | 135 | sigsuspend(&sigs); |
132 | 136 | ||
133 | count = os_write_file(pipe_fd, &c, sizeof(c)); | 137 | count = os_write_file(pipe_fd, &c, sizeof(c)); |
@@ -137,10 +141,10 @@ static int winch_thread(void *arg) | |||
137 | } | 141 | } |
138 | } | 142 | } |
139 | 143 | ||
140 | static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out) | 144 | static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, |
145 | unsigned long *stack_out) | ||
141 | { | 146 | { |
142 | struct winch_data data; | 147 | struct winch_data data; |
143 | unsigned long stack; | ||
144 | int fds[2], n, err; | 148 | int fds[2], n, err; |
145 | char c; | 149 | char c; |
146 | 150 | ||
@@ -153,9 +157,11 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out) | |||
153 | data = ((struct winch_data) { .pty_fd = fd, | 157 | data = ((struct winch_data) { .pty_fd = fd, |
154 | .pipe_fd = fds[1] } ); | 158 | .pipe_fd = fds[1] } ); |
155 | /* CLONE_FILES so this thread doesn't hold open files which are open | 159 | /* CLONE_FILES so this thread doesn't hold open files which are open |
156 | * now, but later closed. This is a problem with /dev/net/tun. | 160 | * now, but later closed in a different thread. This is a |
161 | * problem with /dev/net/tun, which if held open by this | ||
162 | * thread, prevents the TUN/TAP device from being reused. | ||
157 | */ | 163 | */ |
158 | err = run_helper_thread(winch_thread, &data, CLONE_FILES, &stack, 0); | 164 | err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out, 0); |
159 | if(err < 0){ | 165 | if(err < 0){ |
160 | printk("fork of winch_thread failed - errno = %d\n", -err); | 166 | printk("fork of winch_thread failed - errno = %d\n", -err); |
161 | goto out_close; | 167 | goto out_close; |
@@ -187,25 +193,25 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out) | |||
187 | 193 | ||
188 | void register_winch(int fd, struct tty_struct *tty) | 194 | void register_winch(int fd, struct tty_struct *tty) |
189 | { | 195 | { |
190 | int pid, thread, thread_fd = -1; | 196 | unsigned long stack; |
191 | int count; | 197 | int pid, thread, count, thread_fd = -1; |
192 | char c = 1; | 198 | char c = 1; |
193 | 199 | ||
194 | if(!isatty(fd)) | 200 | if(!isatty(fd)) |
195 | return; | 201 | return; |
196 | 202 | ||
197 | pid = tcgetpgrp(fd); | 203 | pid = tcgetpgrp(fd); |
198 | if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, | 204 | if (!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, tty) && |
199 | tty) && (pid == -1)){ | 205 | (pid == -1)) { |
200 | thread = winch_tramp(fd, tty, &thread_fd); | 206 | thread = winch_tramp(fd, tty, &thread_fd, &stack); |
201 | if(thread > 0){ | 207 | if (thread < 0) |
202 | register_winch_irq(thread_fd, fd, thread, tty); | 208 | return; |
203 | 209 | ||
204 | count = os_write_file(thread_fd, &c, sizeof(c)); | 210 | register_winch_irq(thread_fd, fd, thread, tty, stack); |
205 | if(count != sizeof(c)) | 211 | |
206 | printk("register_winch : failed to write " | 212 | count = os_write_file(thread_fd, &c, sizeof(c)); |
207 | "synchronization byte, err = %d\n", | 213 | if(count != sizeof(c)) |
208 | -count); | 214 | printk("register_winch : failed to write " |
209 | } | 215 | "synchronization byte, err = %d\n", -count); |
210 | } | 216 | } |
211 | } | 217 | } |