From 3c4cd4afe93bcfc60be9580e2359c08ca59c945d Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Tue, 27 Sep 2011 21:59:42 -0400 Subject: [PATCH 01/14] Add a header for signal handling --- include/freerdp/utils/signal.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 include/freerdp/utils/signal.h diff --git a/include/freerdp/utils/signal.h b/include/freerdp/utils/signal.h new file mode 100644 index 000000000..faa8ec834 --- /dev/null +++ b/include/freerdp/utils/signal.h @@ -0,0 +1,32 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Signal handling + * + * Copyright 2011 Shea Levy + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __UTILS_SIGNAL_H +#define __UTILS_SIGNAL_H + +#include + +extern volatile sig_atomic_t terminal_needs_reset; +extern int terminal_fildes; +extern struct termios orig_flags; +extern struct termios new_flags; + +FREERDP_API void freerdp_handle_signals(void); + +#endif /* __UTILS_SIGNAL_H */ From 3d1041e8eec16fea9abedb6946f4d0b19b0bc49c Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Tue, 27 Sep 2011 22:32:19 -0400 Subject: [PATCH 02/14] Add a stub for freerdp_handle_signals --- libfreerdp-utils/signal.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 libfreerdp-utils/signal.c diff --git a/libfreerdp-utils/signal.c b/libfreerdp-utils/signal.c new file mode 100644 index 000000000..43607d29c --- /dev/null +++ b/libfreerdp-utils/signal.c @@ -0,0 +1,28 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Signal handling + * + * Copyright 2011 Shea Levy + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +volatile sig_atomic_t terminal_needs_reset = 0; +int terminal_fildes = 0; +struct termios orig_flags; +struct termios new_flags; + +void freerdp_handle_signals(void) +{ +} From ae2018fef8be2d1704207eb654b8f17195a082f2 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Tue, 27 Sep 2011 22:33:55 -0400 Subject: [PATCH 03/14] Compile signal.c --- libfreerdp-utils/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/libfreerdp-utils/CMakeLists.txt b/libfreerdp-utils/CMakeLists.txt index cc941cc23..9daea12ac 100644 --- a/libfreerdp-utils/CMakeLists.txt +++ b/libfreerdp-utils/CMakeLists.txt @@ -39,6 +39,7 @@ set(FREERDP_UTILS_SRCS registry.c certstore.c semaphore.c + signal.c sleep.c stopwatch.c stream.c From 48f474316d4223ed732aedf59afbe0fdb12ae58f Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Tue, 27 Sep 2011 23:35:12 -0400 Subject: [PATCH 04/14] Missing includes in signal.h --- include/freerdp/utils/signal.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/freerdp/utils/signal.h b/include/freerdp/utils/signal.h index faa8ec834..e5f7b4915 100644 --- a/include/freerdp/utils/signal.h +++ b/include/freerdp/utils/signal.h @@ -20,6 +20,8 @@ #ifndef __UTILS_SIGNAL_H #define __UTILS_SIGNAL_H +#include +#include #include extern volatile sig_atomic_t terminal_needs_reset; From 5aea0e2e0c1fa915b7948649a6511f172e03bc32 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Wed, 28 Sep 2011 00:04:36 -0400 Subject: [PATCH 05/14] Add test to check that handle_signals resets the terminal --- cunit/test_utils.c | 40 ++++++++++++++++++++++++++++++++++++++++ cunit/test_utils.h | 1 + 2 files changed, 41 insertions(+) diff --git a/cunit/test_utils.c b/cunit/test_utils.c index 395ff4d6d..753dd890e 100644 --- a/cunit/test_utils.c +++ b/cunit/test_utils.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "test_utils.h" @@ -58,6 +59,7 @@ int add_utils_suite(void) add_test_function(wait_obj); add_test_function(args); add_test_function(passphrase_read); + add_test_function(handle_signals); return 0; } @@ -629,3 +631,41 @@ void test_passphrase_read(void) passphrase_read_prompts_to_stderr_when_no_tty(); passphrase_read_reads_from_stdin_when_no_tty(); } + +void handle_signals_resets_terminal(void) +{ + int status, masterfd; + char* slavedevice; + struct termios test_flags; + + masterfd = posix_openpt(O_RDWR|O_NOCTTY); + + if (masterfd == -1 + || grantpt (masterfd) == -1 + || unlockpt (masterfd) == -1 + || (slavedevice = ptsname (masterfd)) == NULL) + CU_FAIL_FATAL("Could not create pty"); + + terminal_fildes = open(slavedevice, O_RDWR|O_NOCTTY); + tcgetattr(terminal_fildes, &orig_flags); + new_flags = orig_flags; + new_flags.c_lflag &= ~ECHO; + tcsetattr(terminal_fildes, TCSANOW, &new_flags); + terminal_needs_reset = 1; + + if(fork() == 0) + { + freerdp_handle_signals(); + raise(SIGINT); + } + wait(&status); + tcgetattr(terminal_fildes, &test_flags); + CU_ASSERT_EQUAL(orig_flags.c_lflag, test_flags.c_lflag); + close(masterfd); + close(terminal_fildes); +} + +void test_handle_signals(void) +{ + handle_signals_resets_terminal(); +} diff --git a/cunit/test_utils.h b/cunit/test_utils.h index 39cae3920..1bc37d9ef 100644 --- a/cunit/test_utils.h +++ b/cunit/test_utils.h @@ -29,3 +29,4 @@ void test_load_plugin(void); void test_wait_obj(void); void test_args(void); void test_passphrase_read(void); +void test_handle_signals(void); From 6ad931bebdec67277d610a9b9a1d24878e053cfe Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Wed, 28 Sep 2011 01:01:25 -0400 Subject: [PATCH 06/14] Actually wait for the child process to stop --- cunit/test_utils.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cunit/test_utils.c b/cunit/test_utils.c index 753dd890e..cbae793a1 100644 --- a/cunit/test_utils.c +++ b/cunit/test_utils.c @@ -637,6 +637,7 @@ void handle_signals_resets_terminal(void) int status, masterfd; char* slavedevice; struct termios test_flags; + pid_t child_pid; masterfd = posix_openpt(O_RDWR|O_NOCTTY); @@ -653,12 +654,12 @@ void handle_signals_resets_terminal(void) tcsetattr(terminal_fildes, TCSANOW, &new_flags); terminal_needs_reset = 1; - if(fork() == 0) + if((child_pid = fork()) == 0) { freerdp_handle_signals(); raise(SIGINT); } - wait(&status); + while(wait(&status) != -1); tcgetattr(terminal_fildes, &test_flags); CU_ASSERT_EQUAL(orig_flags.c_lflag, test_flags.c_lflag); close(masterfd); From 77bffc4afb0e2ba026d9f2c66e394b289abf6812 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Wed, 28 Sep 2011 01:15:42 -0400 Subject: [PATCH 07/14] freerdp_handle_signals: Reset the terminal for a fatal signal --- libfreerdp-utils/signal.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/libfreerdp-utils/signal.c b/libfreerdp-utils/signal.c index 43607d29c..aef4ce7a5 100644 --- a/libfreerdp-utils/signal.c +++ b/libfreerdp-utils/signal.c @@ -17,12 +17,49 @@ * limitations under the License. */ +#include #include volatile sig_atomic_t terminal_needs_reset = 0; int terminal_fildes = 0; struct termios orig_flags; struct termios new_flags; +static void fatal_handler(int signum) +{ + struct sigaction default_sigaction; + + if (terminal_needs_reset) + tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags); + + default_sigaction.sa_handler = SIG_DFL; + sigfillset(&(default_sigaction.sa_mask)); + default_sigaction.sa_flags = 0; + + sigaction(signum, &default_sigaction, NULL); + raise(signum); +} + void freerdp_handle_signals(void) { + const int fatal_signals[] = { SIGINT }; + int signal_index; + sigset_t orig_set; + struct sigaction orig_sigaction, fatal_sigaction; + + sigfillset(&(fatal_sigaction.sa_mask)); + pthread_sigmask(SIG_BLOCK, &(fatal_sigaction.sa_mask), &orig_set); + + fatal_sigaction.sa_handler = fatal_handler; + fatal_sigaction.sa_flags = 0; + + for (signal_index = 0; + signal_index < (sizeof fatal_signals / sizeof fatal_signals[0]); + signal_index++) + if (sigaction(fatal_signals[signal_index], + NULL, &orig_sigaction) == 0) + if (orig_sigaction.sa_handler != SIG_IGN) + sigaction(fatal_signals[signal_index], + &fatal_sigaction, NULL); + + pthread_sigmask(SIG_SETMASK, &orig_set, NULL); } From 5c20c225475150d20f3a6754308ddf49de9a0d59 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Wed, 28 Sep 2011 01:21:38 -0400 Subject: [PATCH 08/14] freerdp_handle_signals: Handle all POSIX-specified fatal signals --- libfreerdp-utils/signal.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/libfreerdp-utils/signal.c b/libfreerdp-utils/signal.c index aef4ce7a5..573c7b78e 100644 --- a/libfreerdp-utils/signal.c +++ b/libfreerdp-utils/signal.c @@ -41,7 +41,37 @@ static void fatal_handler(int signum) void freerdp_handle_signals(void) { - const int fatal_signals[] = { SIGINT }; + const int fatal_signals[] = { + SIGABRT, + SIGALRM, + SIGBUS, + SIGFPE, + SIGHUP, + SIGILL, + SIGINT, + SIGKILL, + SIGPIPE, + SIGQUIT, + SIGSEGV, + SIGTERM, + SIGUSR1, + SIGUSR2, +#ifdef SIGPOLL + SIGPOLL, +#endif +#ifdef SIGPROF + SIGPROF, +#endif +#ifdef SIGSYS + SIGSYS, +#endif + SIGTRAP, +#ifdef SIGVTALRM + SIGVTALRM, +#endif + SIGXCPU, + SIGXFSZ + }; int signal_index; sigset_t orig_set; struct sigaction orig_sigaction, fatal_sigaction; From a87b4e56716217c8108a35155ec8f9956ca3a448 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Wed, 28 Sep 2011 01:27:14 -0400 Subject: [PATCH 09/14] xfreerdp: Handle signals on start --- client/X11/xfreerdp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index 633c05630..92e9c4f20 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -822,6 +822,8 @@ int main(int argc, char* argv[]) struct thread_data* data; rdpChanMan* chanman; + freerdp_handle_signals(); + setlocale(LC_ALL, ""); freerdp_chanman_global_init(); From 79551abb1b729ad0e9b263a333b70fe9de1f7a56 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Wed, 28 Sep 2011 01:37:43 -0400 Subject: [PATCH 10/14] passphrase: Use the global values the signal handler needs --- libfreerdp-utils/passphrase.c | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/libfreerdp-utils/passphrase.c b/libfreerdp-utils/passphrase.c index 220b695bd..d207cc854 100644 --- a/libfreerdp-utils/passphrase.c +++ b/libfreerdp-utils/passphrase.c @@ -32,16 +32,16 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz) #include #include #include +#include char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz) { char read_char; char* buf_iter; char term_name[L_ctermid]; - int term_file, write_file, read_file, reset_terminal = 0; + int term_file, write_file; ssize_t nbytes; size_t read_bytes = 0; - struct termios orig_flags, no_echo_flags; if (bufsiz == 0) { @@ -54,29 +54,29 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz) || (term_file = open(term_name, O_RDWR)) == -1) { write_file = STDERR_FILENO; - read_file = STDIN_FILENO; + terminal_fildes = STDIN_FILENO; } else { write_file = term_file; - read_file = term_file; + terminal_fildes = term_file; } - if (tcgetattr(read_file, &orig_flags) != -1) + if (tcgetattr(terminal_fildes, &orig_flags) != -1) { - reset_terminal = 1; - no_echo_flags = orig_flags; - no_echo_flags.c_lflag &= ~ECHO; - no_echo_flags.c_lflag |= ECHONL; - if (tcsetattr(read_file, TCSAFLUSH, &no_echo_flags) == -1) - reset_terminal = 0; + new_flags = orig_flags; + new_flags.c_lflag &= ~ECHO; + new_flags.c_lflag |= ECHONL; + terminal_needs_reset = 1; + if (tcsetattr(terminal_fildes, TCSAFLUSH, &new_flags) == -1) + terminal_needs_reset = 0; } if (write(write_file, prompt, strlen(prompt)) == (ssize_t) -1) goto error; buf_iter = buf; - while ((nbytes = read(read_file, &read_char, sizeof read_char)) == (sizeof read_char)) + while ((nbytes = read(terminal_fildes, &read_char, sizeof read_char)) == (sizeof read_char)) { if (read_char == '\n') break; @@ -93,16 +93,16 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz) if (nbytes == (ssize_t) -1) goto error; - if (reset_terminal) + if (terminal_needs_reset) { - if (tcsetattr(read_file, TCSADRAIN, &orig_flags) == -1) + if (tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags) == -1) goto error; - reset_terminal = 0; + terminal_needs_reset = 0; } - if (read_file != STDIN_FILENO) + if (terminal_fildes != STDIN_FILENO) { - if (close(read_file) == -1) + if (close(terminal_fildes) == -1) goto error; } @@ -113,10 +113,10 @@ char* freerdp_passphrase_read(const char* prompt, char* buf, size_t bufsiz) int saved_errno = errno; buf_iter = NULL; read_char = '\0'; - if (reset_terminal) - tcsetattr(read_file, TCSANOW, &orig_flags); - if (read_file != STDIN_FILENO) - close(read_file); + if (terminal_needs_reset) + tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags); + if (terminal_fildes != STDIN_FILENO) + close(terminal_fildes); errno = saved_errno; return NULL; } From 4dc28ae04a4b08991e425b61613930c7306cf0ab Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Wed, 28 Sep 2011 02:09:52 -0400 Subject: [PATCH 11/14] Handle the stopping signals, explicitly unblock the signal before re-raising it in the handler --- libfreerdp-utils/signal.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libfreerdp-utils/signal.c b/libfreerdp-utils/signal.c index 573c7b78e..8d68547f5 100644 --- a/libfreerdp-utils/signal.c +++ b/libfreerdp-utils/signal.c @@ -27,6 +27,7 @@ struct termios new_flags; static void fatal_handler(int signum) { struct sigaction default_sigaction; + sigset_t this_mask; if (terminal_needs_reset) tcsetattr(terminal_fildes, TCSAFLUSH, &orig_flags); @@ -36,6 +37,10 @@ static void fatal_handler(int signum) default_sigaction.sa_flags = 0; sigaction(signum, &default_sigaction, NULL); + + sigemptyset(&this_mask); + sigaddset(&this_mask, signum); + pthread_sigmask(SIG_UNBLOCK, &this_mask, NULL); raise(signum); } @@ -53,7 +58,11 @@ void freerdp_handle_signals(void) SIGPIPE, SIGQUIT, SIGSEGV, + SIGSTOP, SIGTERM, + SIGTSTP, + SIGTTIN, + SIGTTOU, SIGUSR1, SIGUSR2, #ifdef SIGPOLL From 71da4593c2b24a58c4ee70082996b8794c610565 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Wed, 28 Sep 2011 02:40:35 -0400 Subject: [PATCH 12/14] Don't block SIGCONT --- libfreerdp-utils/signal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libfreerdp-utils/signal.c b/libfreerdp-utils/signal.c index 8d68547f5..d926642ab 100644 --- a/libfreerdp-utils/signal.c +++ b/libfreerdp-utils/signal.c @@ -86,6 +86,7 @@ void freerdp_handle_signals(void) struct sigaction orig_sigaction, fatal_sigaction; sigfillset(&(fatal_sigaction.sa_mask)); + sigdelset(&(fatal_sigaction.sa_mask), SIGCONT); pthread_sigmask(SIG_BLOCK, &(fatal_sigaction.sa_mask), &orig_set); fatal_sigaction.sa_handler = fatal_handler; From aed1a8f129d76d1d348244eede5f63d237e82766 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Wed, 28 Sep 2011 02:48:18 -0400 Subject: [PATCH 13/14] Make freerdp_handle_signals return an int, return -1 and set errno to ENOSYS on Windows for now --- include/freerdp/utils/signal.h | 4 +++- libfreerdp-utils/signal.c | 12 +++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/freerdp/utils/signal.h b/include/freerdp/utils/signal.h index e5f7b4915..5682a418e 100644 --- a/include/freerdp/utils/signal.h +++ b/include/freerdp/utils/signal.h @@ -20,6 +20,7 @@ #ifndef __UTILS_SIGNAL_H #define __UTILS_SIGNAL_H +#ifndef _WIN32 #include #include #include @@ -28,7 +29,8 @@ extern volatile sig_atomic_t terminal_needs_reset; extern int terminal_fildes; extern struct termios orig_flags; extern struct termios new_flags; +#endif -FREERDP_API void freerdp_handle_signals(void); +FREERDP_API int freerdp_handle_signals(void); #endif /* __UTILS_SIGNAL_H */ diff --git a/libfreerdp-utils/signal.c b/libfreerdp-utils/signal.c index d926642ab..8f9f67520 100644 --- a/libfreerdp-utils/signal.c +++ b/libfreerdp-utils/signal.c @@ -19,6 +19,14 @@ #include #include +#ifdef _WIN32 +#include +int freerdp_handle_signals(void) +{ + errno = ENOSYS; + return -1; +} +#else volatile sig_atomic_t terminal_needs_reset = 0; int terminal_fildes = 0; struct termios orig_flags; @@ -44,7 +52,7 @@ static void fatal_handler(int signum) raise(signum); } -void freerdp_handle_signals(void) +int freerdp_handle_signals(void) { const int fatal_signals[] = { SIGABRT, @@ -102,4 +110,6 @@ void freerdp_handle_signals(void) &fatal_sigaction, NULL); pthread_sigmask(SIG_SETMASK, &orig_set, NULL); + return 0; } +#endif From 704d290df5320fbb1b79b7dc4884637b68612900 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Wed, 28 Sep 2011 03:11:15 -0400 Subject: [PATCH 14/14] signal.h: We still need api.h on WIN32 --- include/freerdp/utils/signal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/freerdp/utils/signal.h b/include/freerdp/utils/signal.h index 5682a418e..eb54c3f7d 100644 --- a/include/freerdp/utils/signal.h +++ b/include/freerdp/utils/signal.h @@ -20,10 +20,10 @@ #ifndef __UTILS_SIGNAL_H #define __UTILS_SIGNAL_H +#include #ifndef _WIN32 #include #include -#include extern volatile sig_atomic_t terminal_needs_reset; extern int terminal_fildes;