uterm: vt: allow VT-deactivation to fail
If we dispatch VT-deactivation to child-processes, we might allow them to abort the VT-switch, so the upper layer (uterm_vt) must also allow us to abort the VT-switch. During shutdown, we need to force the deactivation to guarantee that a VT is inactive during shutdown. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
parent
68af064040
commit
e7c8e7b531
@ -281,13 +281,14 @@ static void seat_remove_display(struct kmscon_seat *seat,
|
||||
free(d);
|
||||
}
|
||||
|
||||
static int seat_vt_event(struct uterm_vt *vt, unsigned int event, void *data)
|
||||
static int seat_vt_event(struct uterm_vt *vt, struct uterm_vt_event *ev,
|
||||
void *data)
|
||||
{
|
||||
struct kmscon_seat *seat = data;
|
||||
struct shl_dlist *iter;
|
||||
struct kmscon_display *d;
|
||||
|
||||
switch (event) {
|
||||
switch (ev->action) {
|
||||
case UTERM_VT_ACTIVATE:
|
||||
seat->awake = true;
|
||||
if (seat->cb)
|
||||
|
11
src/uterm.h
11
src/uterm.h
@ -352,12 +352,21 @@ enum uterm_vt_action {
|
||||
UTERM_VT_DEACTIVATE,
|
||||
};
|
||||
|
||||
enum uterm_vt_flags {
|
||||
UTERM_VT_FORCE = 0x01,
|
||||
};
|
||||
|
||||
struct uterm_vt_event {
|
||||
unsigned int action;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
enum uterm_vt_mode {
|
||||
UTERM_VT_REAL,
|
||||
UTERM_VT_FAKE,
|
||||
};
|
||||
|
||||
typedef int (*uterm_vt_cb) (struct uterm_vt *vt, unsigned int action,
|
||||
typedef int (*uterm_vt_cb) (struct uterm_vt *vt, struct uterm_vt_event *ev,
|
||||
void *data);
|
||||
|
||||
int uterm_vt_master_new(struct uterm_vt_master **out,
|
||||
|
@ -80,34 +80,59 @@ struct uterm_vt_master {
|
||||
struct shl_dlist vts;
|
||||
};
|
||||
|
||||
static void vt_call(struct uterm_vt *vt, unsigned int event)
|
||||
static int vt_call(struct uterm_vt *vt, unsigned int event, bool force)
|
||||
{
|
||||
int ret;
|
||||
struct uterm_vt_event ev;
|
||||
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.action = event;
|
||||
if (force)
|
||||
ev.flags |= UTERM_VT_FORCE;
|
||||
|
||||
switch (event) {
|
||||
case UTERM_VT_ACTIVATE:
|
||||
if (!vt->active) {
|
||||
if (vt->cb) {
|
||||
ret = vt->cb(vt, event, vt->data);
|
||||
if (ret)
|
||||
log_warning("vt event handler returned %d instead of 0 on activation",
|
||||
ret);
|
||||
}
|
||||
vt->active = true;
|
||||
}
|
||||
if (vt->active)
|
||||
return 0;
|
||||
if (!vt->cb)
|
||||
break;
|
||||
|
||||
ret = vt->cb(vt, &ev, vt->data);
|
||||
if (ret)
|
||||
log_warning("vt event handler returned %d instead of 0 on activation",
|
||||
ret);
|
||||
break;
|
||||
case UTERM_VT_DEACTIVATE:
|
||||
if (vt->active) {
|
||||
if (vt->cb) {
|
||||
ret = vt->cb(vt, event, vt->data);
|
||||
if (ret)
|
||||
log_warning("vt event handler returned %d instead of 0 on deactivation",
|
||||
ret);
|
||||
}
|
||||
vt->active = false;
|
||||
if (!vt->active)
|
||||
return 0;
|
||||
if (!vt->cb)
|
||||
break;
|
||||
|
||||
ret = vt->cb(vt, &ev, vt->data);
|
||||
if (ret) {
|
||||
if (force)
|
||||
log_warning("vt event handler returned %d instead of 0 on forced deactivation",
|
||||
ret);
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vt->active = !vt->active;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vt_call_activate(struct uterm_vt *vt)
|
||||
{
|
||||
vt_call(vt, UTERM_VT_ACTIVATE, false);
|
||||
}
|
||||
|
||||
static int vt_call_deactivate(struct uterm_vt *vt, bool force)
|
||||
{
|
||||
return vt_call(vt, UTERM_VT_DEACTIVATE, force);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -147,7 +172,7 @@ static void real_delayed(struct ev_eloop *eloop, void *unused, void *data)
|
||||
log_debug("enter VT %d %p during startup", vt->real_num, vt);
|
||||
vt->real_delayed = false;
|
||||
ev_eloop_unregister_idle_cb(eloop, real_delayed, vt);
|
||||
vt_call(vt, UTERM_VT_ACTIVATE);
|
||||
vt_call_activate(vt);
|
||||
}
|
||||
|
||||
static void real_sig_enter(struct uterm_vt *vt, struct signalfd_siginfo *info)
|
||||
@ -182,7 +207,7 @@ static void real_sig_enter(struct uterm_vt *vt, struct signalfd_siginfo *info)
|
||||
if (ioctl(vt->real_fd, KDSETMODE, KD_GRAPHICS))
|
||||
log_warn("cannot set graphics mode on vt %p (%d): %m", vt,
|
||||
errno);
|
||||
vt_call(vt, UTERM_VT_ACTIVATE);
|
||||
vt_call_activate(vt);
|
||||
}
|
||||
|
||||
static void real_sig_leave(struct uterm_vt *vt, struct signalfd_siginfo *info)
|
||||
@ -214,7 +239,12 @@ static void real_sig_leave(struct uterm_vt *vt, struct signalfd_siginfo *info)
|
||||
}
|
||||
|
||||
log_debug("leaving VT %d %p due to VT signal", vt->real_num, vt);
|
||||
vt_call(vt, UTERM_VT_DEACTIVATE);
|
||||
ret = vt_call_deactivate(vt, false);
|
||||
if (ret) {
|
||||
ioctl(vt->real_fd, VT_RELDISP, 0);
|
||||
log_debug("not leaving VT %d %p", vt->real_num, vt);
|
||||
return;
|
||||
}
|
||||
ioctl(vt->real_fd, VT_RELDISP, 1);
|
||||
if (ioctl(vt->real_fd, KDSETMODE, KD_TEXT))
|
||||
log_warn("cannot set text mode on vt %p (%d): %m", vt, errno);
|
||||
@ -427,7 +457,7 @@ static void real_close(struct uterm_vt *vt)
|
||||
|
||||
log_debug("closing VT %d", vt->real_num);
|
||||
|
||||
vt_call(vt, UTERM_VT_DEACTIVATE);
|
||||
vt_call_deactivate(vt, true);
|
||||
if (vt->real_delayed) {
|
||||
vt->real_delayed = false;
|
||||
ev_eloop_unregister_idle_cb(vt->vtm->eloop, real_delayed, vt);
|
||||
@ -616,15 +646,14 @@ static void real_input(struct uterm_vt *vt, struct uterm_input_event *ev)
|
||||
static int fake_activate(struct uterm_vt *vt)
|
||||
{
|
||||
log_debug("activating fake VT due to user request");
|
||||
vt_call(vt, UTERM_VT_ACTIVATE);
|
||||
vt_call_activate(vt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fake_deactivate(struct uterm_vt *vt)
|
||||
{
|
||||
log_debug("deactivating fake VT due to user request");
|
||||
vt_call(vt, UTERM_VT_DEACTIVATE);
|
||||
return 0;
|
||||
return vt_call_deactivate(vt, false);
|
||||
}
|
||||
|
||||
static void fake_input(struct uterm_vt *vt, struct uterm_input_event *ev)
|
||||
@ -637,10 +666,10 @@ static void fake_input(struct uterm_vt *vt, struct uterm_input_event *ev)
|
||||
ev->handled = true;
|
||||
if (vt->active) {
|
||||
log_debug("deactivating fake VT due to user input");
|
||||
vt_call(vt, UTERM_VT_DEACTIVATE);
|
||||
vt_call_deactivate(vt, false);
|
||||
} else {
|
||||
log_debug("activating fake VT due to user input");
|
||||
vt_call(vt, UTERM_VT_ACTIVATE);
|
||||
vt_call_activate(vt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -773,7 +802,7 @@ void uterm_vt_deallocate(struct uterm_vt *vt)
|
||||
if (vt->mode == UTERM_VT_REAL) {
|
||||
real_close(vt);
|
||||
} else if (vt->mode == UTERM_VT_FAKE) {
|
||||
vt_call(vt, UTERM_VT_DEACTIVATE);
|
||||
vt_call_deactivate(vt, true);
|
||||
uterm_input_sleep(vt->input);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user