Skip to content

Commit

Permalink
Fix race condition in linux pty output leading to deadlock
Browse files Browse the repository at this point in the history
  • Loading branch information
tbodt committed Jan 12, 2022
1 parent 530d3d9 commit 8a5dc74
Showing 1 changed file with 14 additions and 11 deletions.
25 changes: 14 additions & 11 deletions app/LinuxPTY.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ struct ios_pty {
struct ios_pty_wq wqs[4];
poll_table pt;

struct work_struct poll_cb_work;
struct work_struct output_work;
struct work_struct cleanup_work;
};


static void ios_pty_output_work(struct work_struct *output_work) {
struct ios_pty *pty = container_of(output_work, struct ios_pty, output_work);
size_t room = Terminal_roomForOutput(pty->terminal);
Expand All @@ -66,8 +65,7 @@ static void ios_pty_output_work(struct work_struct *output_work) {
kvfree(buf);
}

static void ios_pty_cleanup_work(struct work_struct *cleanup_work) {
struct ios_pty *pty = container_of(cleanup_work, struct ios_pty, cleanup_work);
static void ios_pty_cleanup(struct ios_pty *pty) {
for (int i = 0; i < pty->n_wqs; i++)
remove_wait_queue(pty->wqs[i].head, &pty->wqs[i].wq);
fput(pty->ptm);
Expand All @@ -92,7 +90,7 @@ static void ios_pty_cb_send_input(struct linux_tty *linux_tty, const char *data,
}

static void ios_pty_cb_hangup(struct linux_tty *linux_tty) {

// TODO: figure out what this should be doing
}

static struct linux_tty_callbacks ios_pty_callbacks = {
Expand All @@ -101,13 +99,18 @@ static struct linux_tty_callbacks ios_pty_callbacks = {
.hangup = ios_pty_cb_hangup,
};

static int ptm_callback(struct wait_queue_entry *wq_entry, unsigned mode, int flags, void *key) {
struct ios_pty *pty = container_of(wq_entry, struct ios_pty_wq, wq)->pty;
static void ios_pty_poll_cb_work(struct work_struct *work) {
struct ios_pty *pty = container_of(work, struct ios_pty, poll_cb_work);
__poll_t events = vfs_poll(pty->ptm, NULL);
if (events & EPOLLHUP)
schedule_work(&pty->cleanup_work);
if (events & EPOLLIN)
schedule_work(&pty->output_work);
ios_pty_output_work(&pty->output_work);
if (events & EPOLLHUP)
ios_pty_cleanup(pty);
}

static int ptm_callback(struct wait_queue_entry *wq_entry, unsigned mode, int flags, void *key) {
struct ios_pty *pty = container_of(wq_entry, struct ios_pty_wq, wq)->pty;
schedule_work(&pty->poll_cb_work);
return 0;
}

Expand Down Expand Up @@ -147,8 +150,8 @@ struct file *ios_pty_open(nsobj_t *terminal_out) {
}
pty->ptm = ptm_file;

INIT_WORK(&pty->poll_cb_work, ios_pty_poll_cb_work);
INIT_WORK(&pty->output_work, ios_pty_output_work);
INIT_WORK(&pty->cleanup_work, ios_pty_cleanup_work);

pty->pts_rdev = pts_file->f_inode->i_rdev;
pty->terminal = Terminal_terminalWithType_number(MAJOR(pty->pts_rdev), MINOR(pty->pts_rdev));
Expand Down

0 comments on commit 8a5dc74

Please sign in to comment.