vt: fix race-condition in signal handling
Currently, we set up our VT with SIGUSR1/2 signals and after that the user may connect the signal handlers to the eloop. However, if we receive a signal in between, the signal gets lost. Therefore, this simply merges the kmscon_vt_connect_eloop function into kmscon_vt_open as there is no obvious reason to split them. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
parent
068591e395
commit
84248b0ac7
109
src/vt.c
109
src/vt.c
@ -144,6 +144,7 @@ static void vt_enter(struct kmscon_signal *sig, int signum, void *data)
|
||||
log_debug("vt: entering VT\n");
|
||||
|
||||
ioctl(vt->fd, VT_RELDISP, VT_ACKACQ);
|
||||
|
||||
if (ioctl(vt->fd, KDSETMODE, KD_GRAPHICS))
|
||||
log_warning("vt: cannot set graphics mode on vt\n");
|
||||
|
||||
@ -158,7 +159,6 @@ static void vt_leave(struct kmscon_signal *sig, int signum, void *data)
|
||||
if (!vt || vt->fd < 0)
|
||||
return;
|
||||
|
||||
|
||||
if (vt->cb && !vt->cb(vt, KMSCON_VT_LEAVE, vt->data)) {
|
||||
log_debug("vt: leaving VT denied\n");
|
||||
ioctl(vt->fd, VT_RELDISP, 0);
|
||||
@ -181,6 +181,50 @@ static void vt_input(struct kmscon_fd *fd, int mask, void *data)
|
||||
tcflush(vt->fd, TCIFLUSH);
|
||||
}
|
||||
|
||||
static int connect_eloop(struct kmscon_vt *vt, struct kmscon_eloop *eloop)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!vt || !eloop || vt->fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = kmscon_eloop_new_signal(eloop, &vt->sig1, SIGUSR1, vt_leave, vt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = kmscon_eloop_new_signal(eloop, &vt->sig2, SIGUSR2, vt_enter, vt);
|
||||
if (ret)
|
||||
goto err_sig1;
|
||||
|
||||
ret = kmscon_eloop_new_fd(eloop, &vt->efd, vt->fd, KMSCON_READABLE,
|
||||
vt_input, vt);
|
||||
if (ret)
|
||||
goto err_sig2;
|
||||
|
||||
return 0;
|
||||
|
||||
err_sig2:
|
||||
kmscon_eloop_rm_signal(vt->sig2);
|
||||
vt->sig2 = NULL;
|
||||
err_sig1:
|
||||
kmscon_eloop_rm_signal(vt->sig1);
|
||||
vt->sig1 = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void disconnect_eloop(struct kmscon_vt *vt)
|
||||
{
|
||||
if (!vt)
|
||||
return;
|
||||
|
||||
kmscon_eloop_rm_signal(vt->sig1);
|
||||
kmscon_eloop_rm_signal(vt->sig2);
|
||||
kmscon_eloop_rm_fd(vt->efd);
|
||||
vt->sig1 = NULL;
|
||||
vt->sig2 = NULL;
|
||||
vt->efd = NULL;
|
||||
}
|
||||
|
||||
static int open_tty(int id, int *tty_fd, int *tty_num)
|
||||
{
|
||||
int fd;
|
||||
@ -222,7 +266,7 @@ static int open_tty(int id, int *tty_fd, int *tty_num)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kmscon_vt_open(struct kmscon_vt *vt, int id)
|
||||
int kmscon_vt_open(struct kmscon_vt *vt, int id, struct kmscon_eloop *eloop)
|
||||
{
|
||||
struct termios raw_attribs;
|
||||
struct vt_mode mode;
|
||||
@ -237,6 +281,10 @@ int kmscon_vt_open(struct kmscon_vt *vt, int id)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = connect_eloop(vt, eloop);
|
||||
if (ret)
|
||||
goto err_fd;
|
||||
|
||||
/*
|
||||
* Get the number of the VT which is active now, so we have something
|
||||
* to switch back to in kmscon_vt_switch_leave.
|
||||
@ -252,7 +300,7 @@ int kmscon_vt_open(struct kmscon_vt *vt, int id)
|
||||
if (tcgetattr(vt->fd, &vt->saved_attribs) < 0) {
|
||||
log_err("vt: cannot get terminal attributes\n");
|
||||
ret = -EFAULT;
|
||||
goto err_fd;
|
||||
goto err_eloop;
|
||||
}
|
||||
|
||||
/* Ignore control characters and disable echo */
|
||||
@ -293,6 +341,8 @@ err_text:
|
||||
ioctl(vt->fd, KDSETMODE, KD_TEXT);
|
||||
err_reset:
|
||||
tcsetattr(vt->fd, TCSANOW, &vt->saved_attribs);
|
||||
err_eloop:
|
||||
disconnect_eloop(vt);
|
||||
err_fd:
|
||||
close(vt->fd);
|
||||
vt->fd = -1;
|
||||
@ -306,63 +356,14 @@ void kmscon_vt_close(struct kmscon_vt *vt)
|
||||
|
||||
ioctl(vt->fd, KDSETMODE, KD_TEXT);
|
||||
tcsetattr(vt->fd, TCSANOW, &vt->saved_attribs);
|
||||
|
||||
kmscon_vt_disconnect_eloop(vt);
|
||||
disconnect_eloop(vt);
|
||||
close(vt->fd);
|
||||
|
||||
vt->fd = -1;
|
||||
vt->num = -1;
|
||||
vt->saved_num = -1;
|
||||
}
|
||||
|
||||
int kmscon_vt_connect_eloop(struct kmscon_vt *vt, struct kmscon_eloop *loop)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!vt || !loop || vt->fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (vt->sig1 || vt->sig2)
|
||||
return -EALREADY;
|
||||
|
||||
ret = kmscon_eloop_new_signal(loop, &vt->sig1, SIGUSR1, vt_leave,
|
||||
vt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = kmscon_eloop_new_signal(loop, &vt->sig2, SIGUSR2, vt_enter,
|
||||
vt);
|
||||
if (ret)
|
||||
goto err_sig1;
|
||||
|
||||
ret = kmscon_eloop_new_fd(loop, &vt->efd, vt->fd, KMSCON_READABLE,
|
||||
vt_input, vt);
|
||||
if (ret)
|
||||
goto err_sig2;
|
||||
|
||||
return 0;
|
||||
|
||||
err_sig2:
|
||||
kmscon_eloop_rm_signal(vt->sig2);
|
||||
vt->sig2 = NULL;
|
||||
err_sig1:
|
||||
kmscon_eloop_rm_signal(vt->sig1);
|
||||
vt->sig1 = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void kmscon_vt_disconnect_eloop(struct kmscon_vt *vt)
|
||||
{
|
||||
if (!vt)
|
||||
return;
|
||||
|
||||
kmscon_eloop_rm_signal(vt->sig1);
|
||||
kmscon_eloop_rm_signal(vt->sig2);
|
||||
kmscon_eloop_rm_fd(vt->efd);
|
||||
vt->sig1 = NULL;
|
||||
vt->sig2 = NULL;
|
||||
vt->efd = NULL;
|
||||
}
|
||||
|
||||
/* Switch to this VT and make it the active VT. */
|
||||
int kmscon_vt_enter(struct kmscon_vt *vt)
|
||||
{
|
||||
|
6
src/vt.h
6
src/vt.h
@ -58,12 +58,10 @@ int kmscon_vt_new(struct kmscon_vt **out, kmscon_vt_cb cb, void *data);
|
||||
void kmscon_vt_ref(struct kmscon_vt *vt);
|
||||
void kmscon_vt_unref(struct kmscon_vt *vt);
|
||||
|
||||
int kmscon_vt_open(struct kmscon_vt *vt, int id);
|
||||
int kmscon_vt_open(struct kmscon_vt *vt, int id, struct kmscon_eloop *eloop);
|
||||
void kmscon_vt_close(struct kmscon_vt *vt);
|
||||
|
||||
int kmscon_vt_connect_eloop(struct kmscon_vt *vt, struct kmscon_eloop *loop);
|
||||
void kmscon_vt_disconnect_eloop(struct kmscon_vt *vt);
|
||||
|
||||
int kmscon_vt_enter(struct kmscon_vt *vt);
|
||||
int kmscon_vt_leave(struct kmscon_vt *vt);
|
||||
|
||||
#endif /* KMSCON_VT_H */
|
||||
|
@ -285,11 +285,7 @@ static int setup_eloop(struct console *con)
|
||||
if (ret)
|
||||
goto err_loop;
|
||||
|
||||
ret = kmscon_vt_open(con->vt, KMSCON_VT_NEW);
|
||||
if (ret)
|
||||
goto err_loop;
|
||||
|
||||
ret = kmscon_vt_connect_eloop(con->vt, con->loop);
|
||||
ret = kmscon_vt_open(con->vt, KMSCON_VT_NEW, con->loop);
|
||||
if (ret)
|
||||
goto err_loop;
|
||||
|
||||
|
@ -76,18 +76,12 @@ int main(int argc, char **argv)
|
||||
goto err_sig;
|
||||
}
|
||||
|
||||
ret = kmscon_vt_open(vt, KMSCON_VT_NEW);
|
||||
ret = kmscon_vt_open(vt, KMSCON_VT_NEW, loop);
|
||||
if (ret) {
|
||||
log_err("Cannot open VT\n");
|
||||
goto err_vt;
|
||||
}
|
||||
|
||||
ret = kmscon_vt_connect_eloop(vt, loop);
|
||||
if (ret) {
|
||||
log_err("Cannot connect VT\n");
|
||||
goto err_vt;
|
||||
}
|
||||
|
||||
ret = kmscon_vt_enter(vt);
|
||||
if (ret)
|
||||
log_warning("Cannot switch to VT\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user