| Index: native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc | 
| diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc | 
| index 5a2fc7a9743ab6abc8bb9da43f3e85c827e4b504..4b6c5652d01be0a5728c06ead26ff461ee1dae6b 100644 | 
| --- a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc | 
| +++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc | 
| @@ -32,13 +32,16 @@ | 
|  | 
| namespace nacl_io { | 
|  | 
| -MountNodeTty::MountNodeTty(Mount* mount) : MountNodeCharDevice(mount), | 
| -                                           is_readable_(false), | 
| -                                           rows_(DEFAULT_TTY_ROWS), | 
| -                                           cols_(DEFAULT_TTY_COLS) { | 
| +MountNodeTty::MountNodeTty(Mount* mount) | 
| +    : MountNodeCharDevice(mount), | 
| +      emitter_(new EventEmitter), | 
| +      rows_(DEFAULT_TTY_ROWS), | 
| +      cols_(DEFAULT_TTY_COLS) { | 
| output_handler_.handler = NULL; | 
| -  pthread_cond_init(&is_readable_cond_, NULL); | 
| InitTermios(); | 
| + | 
| +  // Output will never block | 
| +  emitter_->RaiseEvents_Locked(POLLOUT); | 
| } | 
|  | 
| void MountNodeTty::InitTermios() { | 
| @@ -69,14 +72,15 @@ void MountNodeTty::InitTermios() { | 
| termios_.c_cc[VEOL2] = 0; | 
| } | 
|  | 
| -MountNodeTty::~MountNodeTty() { | 
| -  pthread_cond_destroy(&is_readable_cond_); | 
| +EventEmitter* MountNodeTty::GetEventEmitter() { | 
| +  return emitter_.get(); | 
| } | 
|  | 
| Error MountNodeTty::Write(size_t offs, | 
| const void* buf, | 
| size_t count, | 
| int* out_bytes) { | 
| + | 
| AUTO_LOCK(output_lock_); | 
| *out_bytes = 0; | 
|  | 
| @@ -97,14 +101,17 @@ Error MountNodeTty::Write(size_t offs, | 
| return 0; | 
| } | 
|  | 
| + | 
| Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) { | 
| -  AUTO_LOCK(node_lock_); | 
| -  while (!is_readable_) { | 
| -    pthread_cond_wait(&is_readable_cond_, node_lock_.mutex()); | 
| -  } | 
| +  EventListenerLock wait(GetEventEmitter()); | 
| +  *out_bytes = 0; | 
|  | 
| -  size_t bytes_to_copy = std::min(count, input_buffer_.size()); | 
| +  // If interrupted, return | 
| +  Error err = wait.WaitOnEvent(POLLIN, -1); | 
| +  if (err != 0) | 
| +    return err; | 
|  | 
| +  size_t bytes_to_copy = std::min(count, input_buffer_.size()); | 
| if (IS_ICANON) { | 
| // Only read up to (and including) the first newline | 
| std::deque<char>::iterator nl = std::find(input_buffer_.begin(), | 
| @@ -129,12 +136,15 @@ Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) { | 
| // mark input as no longer readable if we consumed | 
| // the entire buffer or, in the case of buffered input, | 
| // we consumed the final \n char. | 
| +  bool avail; | 
| if (IS_ICANON) | 
| -    is_readable_ = | 
| -        std::find(input_buffer_.begin(), | 
| -                  input_buffer_.end(), '\n') != input_buffer_.end(); | 
| +    avail = std::find(input_buffer_.begin(), | 
| +                      input_buffer_.end(), '\n') != input_buffer_.end(); | 
| else | 
| -    is_readable_ = input_buffer_.size() > 0; | 
| +    avail = input_buffer_.size() > 0; | 
| + | 
| +  if (!avail) | 
| +    emitter_->ClearEvents_Locked(POLLIN); | 
|  | 
| return 0; | 
| } | 
| @@ -152,7 +162,7 @@ Error MountNodeTty::Echo(const char* string, int count) { | 
| } | 
|  | 
| Error MountNodeTty::ProcessInput(struct tioc_nacl_input_string* message) { | 
| -  AUTO_LOCK(node_lock_); | 
| +  AUTO_LOCK(emitter_->GetLock()) | 
|  | 
| const char* buffer = message->buffer; | 
| size_t num_bytes = message->length; | 
| @@ -212,12 +222,7 @@ Error MountNodeTty::ProcessInput(struct tioc_nacl_input_string* message) { | 
| input_buffer_.push_back(c); | 
|  | 
| if (c == '\n' || c == termios_.c_cc[VEOF] || !IS_ICANON) | 
| -      is_readable_ = true; | 
| -  } | 
| - | 
| -  if (is_readable_) { | 
| -    RaiseEvent(POLLIN); | 
| -    pthread_cond_broadcast(&is_readable_cond_); | 
| +      emitter_->RaiseEvents_Locked(POLLIN); | 
| } | 
|  | 
| return 0; | 
| @@ -251,6 +256,13 @@ Error MountNodeTty::Ioctl(int request, char* arg) { | 
| cols_ = size->ws_col; | 
| } | 
| kill(getpid(), SIGWINCH); | 
| +      { | 
| +        // Wake up any thread waiting on Read with POLLERR then immediate | 
| +        // clear it to signal EINTR. | 
| +        AUTO_LOCK(emitter_->GetLock()) | 
| +        emitter_->RaiseEvents_Locked(POLLERR); | 
| +        emitter_->ClearEvents_Locked(POLLERR); | 
| +      } | 
| return 0; | 
| } | 
| case TIOCGWINSZ: { | 
|  |