mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
terminal: don’t unref a not-yet-referenced key-binding set
Key-binding sets are bound to a seat/configuration pair. The conf reference is done when a new terminal instance is created. When that same terminal instance is destroyed, the key binding set is unref:ed. If the terminal instance is destroyed *before* the key binding set has been referenced, we’ll still unref it. This creates an imbalance. In particular, when the there is exactly one other terminal instance referencing that same key binding set, that terminal instance will trigger a foot server crash as soon as it receives a key press/release event. This happens because the next-to-last terminal instance brought the reference count of the binding set down to 0, causing it to be free:d. Thus, we *must* reference the binding set *before* we can error out (when instantiating a new terminal instance). At this point, we don’t yet have a valid terminal instance. But, that’s ok, because all the key_binding_new_for_term() did with the terminal instance was get the "struct wayland" and "struct config" pointers. So, rename the function and simply pass these pointers explicitly. Similarly, change key_binding_for() to take a "struct config" pointer, rather than a "struct terminal" pointer. Also rename key_binding_unref_term() -> key_binding_unref().
This commit is contained in:
parent
c311229b9e
commit
d2e67689ea
6 changed files with 35 additions and 31 deletions
|
|
@ -80,17 +80,14 @@ key_binding_new_for_seat(struct key_binding_manager *mgr,
|
|||
}
|
||||
|
||||
void
|
||||
key_binding_new_for_term(struct key_binding_manager *mgr,
|
||||
const struct terminal *term)
|
||||
key_binding_new_for_conf(struct key_binding_manager *mgr,
|
||||
const struct wayland *wayl, const struct config *conf)
|
||||
{
|
||||
const struct config *conf = term->conf;
|
||||
const struct wayland *wayl = term->wl;
|
||||
|
||||
tll_foreach(wayl->seats, it) {
|
||||
struct seat *seat = &it->item;
|
||||
|
||||
struct key_set *existing =
|
||||
(struct key_set *)key_binding_for(mgr, term, seat);
|
||||
(struct key_set *)key_binding_for(mgr, conf, seat);
|
||||
|
||||
if (existing != NULL) {
|
||||
existing->conf_ref_count++;
|
||||
|
|
@ -116,21 +113,19 @@ key_binding_new_for_term(struct key_binding_manager *mgr,
|
|||
/* Chances are high this set will be requested next */
|
||||
mgr->last_used_set = &tll_back(mgr->binding_sets);
|
||||
|
||||
LOG_DBG("new (term): set=%p, seat=%p, conf=%p, ref-count=1",
|
||||
LOG_DBG("new (conf): set=%p, seat=%p, conf=%p, ref-count=1",
|
||||
(void *)&tll_back(mgr->binding_sets),
|
||||
(void *)set.seat, (void *)set.conf);
|
||||
}
|
||||
|
||||
LOG_DBG("new (term): total number of sets: %zu",
|
||||
LOG_DBG("new (conf): total number of sets: %zu",
|
||||
tll_length(mgr->binding_sets));
|
||||
}
|
||||
|
||||
struct key_binding_set * NOINLINE
|
||||
key_binding_for(struct key_binding_manager *mgr, const struct terminal *term,
|
||||
key_binding_for(struct key_binding_manager *mgr, const struct config *conf,
|
||||
const struct seat *seat)
|
||||
{
|
||||
const struct config *conf = term->conf;
|
||||
|
||||
struct key_set *last_used = mgr->last_used_set;
|
||||
if (last_used != NULL &&
|
||||
last_used->conf == conf &&
|
||||
|
|
@ -192,11 +187,8 @@ key_binding_remove_seat(struct key_binding_manager *mgr,
|
|||
}
|
||||
|
||||
void
|
||||
key_binding_unref_term(struct key_binding_manager *mgr,
|
||||
const struct terminal *term)
|
||||
key_binding_unref(struct key_binding_manager *mgr, const struct config *conf)
|
||||
{
|
||||
const struct config *conf = term->conf;
|
||||
|
||||
tll_foreach(mgr->binding_sets, it) {
|
||||
struct key_set *set = &it->item;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue