Loading adb/commandline.cpp +39 −13 Original line number Diff line number Diff line Loading @@ -472,18 +472,46 @@ static bool GetFeatureSet(TransportType transport_type, const char* serial, Feat } static void send_window_size_change(int fd, std::unique_ptr<ShellProtocol>& shell) { #if !defined(_WIN32) // Old devices can't handle window size changes. if (shell == nullptr) return; #if defined(_WIN32) struct winsize { unsigned short ws_row; unsigned short ws_col; unsigned short ws_xpixel; unsigned short ws_ypixel; }; #endif winsize ws; #if defined(_WIN32) // If stdout is redirected to a non-console, we won't be able to get the // console size, but that makes sense. const intptr_t intptr_handle = _get_osfhandle(STDOUT_FILENO); if (intptr_handle == -1) return; const HANDLE handle = reinterpret_cast<const HANDLE>(intptr_handle); CONSOLE_SCREEN_BUFFER_INFO info; memset(&info, 0, sizeof(info)); if (!GetConsoleScreenBufferInfo(handle, &info)) return; memset(&ws, 0, sizeof(ws)); // The number of visible rows, excluding offscreen scroll-back rows which are in info.dwSize.Y. ws.ws_row = info.srWindow.Bottom - info.srWindow.Top + 1; // If the user has disabled "Wrap text output on resize", they can make the screen buffer wider // than the window, in which case we should use the width of the buffer. ws.ws_col = info.dwSize.X; #else if (ioctl(fd, TIOCGWINSZ, &ws) == -1) return; #endif // Send the new window size as human-readable ASCII for debugging convenience. size_t l = snprintf(shell->data(), shell->data_capacity(), "%dx%d,%dx%d", ws.ws_row, ws.ws_col, ws.ws_xpixel, ws.ws_ypixel); shell->Write(ShellProtocol::kIdWindowSizeChange, l + 1); #endif } // Used to pass multiple values to the stdin read thread. Loading @@ -508,7 +536,10 @@ static void* stdin_read_thread_loop(void* x) { pthread_sigmask(SIG_BLOCK, &sigset, nullptr); #endif #if !defined(_WIN32) #if defined(_WIN32) // _get_interesting_input_record_uncached() causes unix_read_interruptible() // to return -1 with errno == EINTR if the window size changes. #else // Unblock SIGWINCH for this thread, so our read(2) below will be // interrupted if the window size changes. sigset_t mask; Loading Loading @@ -537,20 +568,15 @@ static void* stdin_read_thread_loop(void* x) { EscapeState state = kStartOfLine; while (true) { // Use unix_read() rather than adb_read() for stdin. D("stdin_read_thread_loop(): pre unix_read(fdi=%d,...)", args->stdin_fd); #if !defined(_WIN32) #undef read int r = read(args->stdin_fd, buffer_ptr, buffer_size); // Use unix_read_interruptible() rather than adb_read() for stdin. D("stdin_read_thread_loop(): pre unix_read_interruptible(fdi=%d,...)", args->stdin_fd); int r = unix_read_interruptible(args->stdin_fd, buffer_ptr, buffer_size); if (r == -1 && errno == EINTR) { send_window_size_change(args->stdin_fd, args->protocol); continue; } #define read ___xxx_read #else int r = unix_read(args->stdin_fd, buffer_ptr, buffer_size); #endif D("stdin_read_thread_loop(): post unix_read(fdi=%d,...)", args->stdin_fd); D("stdin_read_thread_loop(): post unix_read_interruptible(fdi=%d,...)", args->stdin_fd); if (r <= 0) { // Only devices using the shell protocol know to close subprocess // stdin. For older devices we want to just leave the connection Loading adb/sysdeps.h +11 −1 Original line number Diff line number Diff line Loading @@ -164,8 +164,13 @@ static __inline__ int unix_close(int fd) #undef close #define close ____xxx_close // Like unix_read(), but may return EINTR. extern int unix_read_interruptible(int fd, void* buf, size_t len); // See the comments for the !defined(_WIN32) version of unix_read(). extern int unix_read(int fd, void* buf, size_t len); static __inline__ int unix_read(int fd, void* buf, size_t len) { return TEMP_FAILURE_RETRY(unix_read_interruptible(fd, buf, len)); } #undef read #define read ___xxx_read Loading Loading @@ -517,6 +522,11 @@ static __inline__ int adb_read(int fd, void* buf, size_t len) return TEMP_FAILURE_RETRY( read( fd, buf, len ) ); } // Like unix_read(), but does not handle EINTR. static __inline__ int unix_read_interruptible(int fd, void* buf, size_t len) { return read(fd, buf, len); } #undef read #define read ___xxx_read Loading adb/sysdeps_win32.cpp +21 −5 Original line number Diff line number Diff line Loading @@ -2588,6 +2588,18 @@ static bool _get_key_event_record(const HANDLE console, INPUT_RECORD* const inpu fatal("ReadConsoleInputA did not return one input record"); } // If the console window is resized, emulate SIGWINCH by breaking out // of read() with errno == EINTR. Note that there is no event on // vertical resize because we don't give the console our own custom // screen buffer (with CreateConsoleScreenBuffer() + // SetConsoleActiveScreenBuffer()). Instead, we use the default which // supports scrollback, but doesn't seem to raise an event for vertical // window resize. if (input_record->EventType == WINDOW_BUFFER_SIZE_EVENT) { errno = EINTR; return false; } if ((input_record->EventType == KEY_EVENT) && (input_record->Event.KeyEvent.bKeyDown)) { if (input_record->Event.KeyEvent.wRepeatCount == 0) { Loading Loading @@ -3323,9 +3335,13 @@ void stdin_raw_init() { // Disable ENABLE_LINE_INPUT so that input is immediately sent. // Disable ENABLE_ECHO_INPUT to disable local echo. Disabling this // flag also seems necessary to have proper line-ending processing. if (!SetConsoleMode(in, _old_console_mode & ~(ENABLE_PROCESSED_INPUT | DWORD new_console_mode = _old_console_mode & ~(ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT))) { ENABLE_ECHO_INPUT); // Enable ENABLE_WINDOW_INPUT to get window resizes. new_console_mode |= ENABLE_WINDOW_INPUT; if (!SetConsoleMode(in, new_console_mode)) { // This really should not fail. D("stdin_raw_init: SetConsoleMode() failed: %s", SystemErrorCodeToString(GetLastError()).c_str()); Loading Loading @@ -3353,8 +3369,8 @@ void stdin_raw_restore() { } } // Called by 'adb shell' and 'adb exec-in' to read from stdin. int unix_read(int fd, void* buf, size_t len) { // Called by 'adb shell' and 'adb exec-in' (via unix_read()) to read from stdin. int unix_read_interruptible(int fd, void* buf, size_t len) { if ((fd == STDIN_FILENO) && (_console_handle != NULL)) { // If it is a request to read from stdin, and stdin_raw_init() has been // called, and it successfully configured the console, then read from Loading Loading
adb/commandline.cpp +39 −13 Original line number Diff line number Diff line Loading @@ -472,18 +472,46 @@ static bool GetFeatureSet(TransportType transport_type, const char* serial, Feat } static void send_window_size_change(int fd, std::unique_ptr<ShellProtocol>& shell) { #if !defined(_WIN32) // Old devices can't handle window size changes. if (shell == nullptr) return; #if defined(_WIN32) struct winsize { unsigned short ws_row; unsigned short ws_col; unsigned short ws_xpixel; unsigned short ws_ypixel; }; #endif winsize ws; #if defined(_WIN32) // If stdout is redirected to a non-console, we won't be able to get the // console size, but that makes sense. const intptr_t intptr_handle = _get_osfhandle(STDOUT_FILENO); if (intptr_handle == -1) return; const HANDLE handle = reinterpret_cast<const HANDLE>(intptr_handle); CONSOLE_SCREEN_BUFFER_INFO info; memset(&info, 0, sizeof(info)); if (!GetConsoleScreenBufferInfo(handle, &info)) return; memset(&ws, 0, sizeof(ws)); // The number of visible rows, excluding offscreen scroll-back rows which are in info.dwSize.Y. ws.ws_row = info.srWindow.Bottom - info.srWindow.Top + 1; // If the user has disabled "Wrap text output on resize", they can make the screen buffer wider // than the window, in which case we should use the width of the buffer. ws.ws_col = info.dwSize.X; #else if (ioctl(fd, TIOCGWINSZ, &ws) == -1) return; #endif // Send the new window size as human-readable ASCII for debugging convenience. size_t l = snprintf(shell->data(), shell->data_capacity(), "%dx%d,%dx%d", ws.ws_row, ws.ws_col, ws.ws_xpixel, ws.ws_ypixel); shell->Write(ShellProtocol::kIdWindowSizeChange, l + 1); #endif } // Used to pass multiple values to the stdin read thread. Loading @@ -508,7 +536,10 @@ static void* stdin_read_thread_loop(void* x) { pthread_sigmask(SIG_BLOCK, &sigset, nullptr); #endif #if !defined(_WIN32) #if defined(_WIN32) // _get_interesting_input_record_uncached() causes unix_read_interruptible() // to return -1 with errno == EINTR if the window size changes. #else // Unblock SIGWINCH for this thread, so our read(2) below will be // interrupted if the window size changes. sigset_t mask; Loading Loading @@ -537,20 +568,15 @@ static void* stdin_read_thread_loop(void* x) { EscapeState state = kStartOfLine; while (true) { // Use unix_read() rather than adb_read() for stdin. D("stdin_read_thread_loop(): pre unix_read(fdi=%d,...)", args->stdin_fd); #if !defined(_WIN32) #undef read int r = read(args->stdin_fd, buffer_ptr, buffer_size); // Use unix_read_interruptible() rather than adb_read() for stdin. D("stdin_read_thread_loop(): pre unix_read_interruptible(fdi=%d,...)", args->stdin_fd); int r = unix_read_interruptible(args->stdin_fd, buffer_ptr, buffer_size); if (r == -1 && errno == EINTR) { send_window_size_change(args->stdin_fd, args->protocol); continue; } #define read ___xxx_read #else int r = unix_read(args->stdin_fd, buffer_ptr, buffer_size); #endif D("stdin_read_thread_loop(): post unix_read(fdi=%d,...)", args->stdin_fd); D("stdin_read_thread_loop(): post unix_read_interruptible(fdi=%d,...)", args->stdin_fd); if (r <= 0) { // Only devices using the shell protocol know to close subprocess // stdin. For older devices we want to just leave the connection Loading
adb/sysdeps.h +11 −1 Original line number Diff line number Diff line Loading @@ -164,8 +164,13 @@ static __inline__ int unix_close(int fd) #undef close #define close ____xxx_close // Like unix_read(), but may return EINTR. extern int unix_read_interruptible(int fd, void* buf, size_t len); // See the comments for the !defined(_WIN32) version of unix_read(). extern int unix_read(int fd, void* buf, size_t len); static __inline__ int unix_read(int fd, void* buf, size_t len) { return TEMP_FAILURE_RETRY(unix_read_interruptible(fd, buf, len)); } #undef read #define read ___xxx_read Loading Loading @@ -517,6 +522,11 @@ static __inline__ int adb_read(int fd, void* buf, size_t len) return TEMP_FAILURE_RETRY( read( fd, buf, len ) ); } // Like unix_read(), but does not handle EINTR. static __inline__ int unix_read_interruptible(int fd, void* buf, size_t len) { return read(fd, buf, len); } #undef read #define read ___xxx_read Loading
adb/sysdeps_win32.cpp +21 −5 Original line number Diff line number Diff line Loading @@ -2588,6 +2588,18 @@ static bool _get_key_event_record(const HANDLE console, INPUT_RECORD* const inpu fatal("ReadConsoleInputA did not return one input record"); } // If the console window is resized, emulate SIGWINCH by breaking out // of read() with errno == EINTR. Note that there is no event on // vertical resize because we don't give the console our own custom // screen buffer (with CreateConsoleScreenBuffer() + // SetConsoleActiveScreenBuffer()). Instead, we use the default which // supports scrollback, but doesn't seem to raise an event for vertical // window resize. if (input_record->EventType == WINDOW_BUFFER_SIZE_EVENT) { errno = EINTR; return false; } if ((input_record->EventType == KEY_EVENT) && (input_record->Event.KeyEvent.bKeyDown)) { if (input_record->Event.KeyEvent.wRepeatCount == 0) { Loading Loading @@ -3323,9 +3335,13 @@ void stdin_raw_init() { // Disable ENABLE_LINE_INPUT so that input is immediately sent. // Disable ENABLE_ECHO_INPUT to disable local echo. Disabling this // flag also seems necessary to have proper line-ending processing. if (!SetConsoleMode(in, _old_console_mode & ~(ENABLE_PROCESSED_INPUT | DWORD new_console_mode = _old_console_mode & ~(ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT))) { ENABLE_ECHO_INPUT); // Enable ENABLE_WINDOW_INPUT to get window resizes. new_console_mode |= ENABLE_WINDOW_INPUT; if (!SetConsoleMode(in, new_console_mode)) { // This really should not fail. D("stdin_raw_init: SetConsoleMode() failed: %s", SystemErrorCodeToString(GetLastError()).c_str()); Loading Loading @@ -3353,8 +3369,8 @@ void stdin_raw_restore() { } } // Called by 'adb shell' and 'adb exec-in' to read from stdin. int unix_read(int fd, void* buf, size_t len) { // Called by 'adb shell' and 'adb exec-in' (via unix_read()) to read from stdin. int unix_read_interruptible(int fd, void* buf, size_t len) { if ((fd == STDIN_FILENO) && (_console_handle != NULL)) { // If it is a request to read from stdin, and stdin_raw_init() has been // called, and it successfully configured the console, then read from Loading