static struct spk_synth *spk_ttyio_synth;
 static struct tty_struct *speakup_tty;
+/* mutex to protect against speakup_tty disappearing from underneath us while
+ * we are using it. this can happen when the device physically unplugged,
+ * while in use. it also serialises access to speakup_tty.
+ */
+static DEFINE_MUTEX(speakup_tty_mutex);
 
 static int ser_to_dev(int ser, dev_t *dev_no)
 {
 
 static void spk_ttyio_ldisc_close(struct tty_struct *tty)
 {
+       mutex_lock(&speakup_tty_mutex);
        kfree(speakup_tty->disc_data);
        speakup_tty = NULL;
+       mutex_unlock(&speakup_tty_mutex);
 }
 
 static int spk_ttyio_receive_buf2(struct tty_struct *tty,
 
 static int spk_ttyio_out(struct spk_synth *in_synth, const char ch)
 {
+       mutex_lock(&speakup_tty_mutex);
        if (in_synth->alive && speakup_tty && speakup_tty->ops->write) {
                int ret = speakup_tty->ops->write(speakup_tty, &ch, 1);
 
+               mutex_unlock(&speakup_tty_mutex);
                if (ret == 0)
                        /* No room */
                        return 0;
                }
                return 1;
        }
+
+       mutex_unlock(&speakup_tty_mutex);
+       return 0;
+}
+
+static int check_tty(struct tty_struct *tty)
+{
+       if (!tty) {
+               pr_warn("%s: I/O error, deactivating speakup\n",
+                       spk_ttyio_synth->long_name);
+               /* No synth any more, so nobody will restart TTYs, and we thus
+                * need to do it ourselves.  Now that there is no synth we can
+                * let application flood anyway
+                */
+               spk_ttyio_synth->alive = 0;
+               speakup_start_ttys();
+               return 1;
+       }
+
        return 0;
 }
 
 static void spk_ttyio_send_xchar(char ch)
 {
+       mutex_lock(&speakup_tty_mutex);
+       if (check_tty(speakup_tty)) {
+               mutex_unlock(&speakup_tty_mutex);
+               return;
+       }
+
        speakup_tty->ops->send_xchar(speakup_tty, ch);
+       mutex_unlock(&speakup_tty_mutex);
 }
 
 static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
 {
+       mutex_lock(&speakup_tty_mutex);
+       if (check_tty(speakup_tty)) {
+               mutex_unlock(&speakup_tty_mutex);
+               return;
+       }
+
        speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+       mutex_unlock(&speakup_tty_mutex);
 }
 
 static unsigned char ttyio_in(int timeout)
 
 static void spk_ttyio_flush_buffer(void)
 {
+       mutex_lock(&speakup_tty_mutex);
+       if (check_tty(speakup_tty)) {
+               mutex_unlock(&speakup_tty_mutex);
+               return;
+       }
+
        if (speakup_tty->ops->flush_buffer)
                speakup_tty->ops->flush_buffer(speakup_tty);
+
+       mutex_unlock(&speakup_tty_mutex);
 }
 
 int spk_ttyio_synth_probe(struct spk_synth *synth)