Make the device hold a reference to its controls.

Without this, if "-a on" is used, when the last control client
disconnects, references reach zero and controls are freed.
This commit is contained in:
Alexandre Ratchov 2020-01-14 18:04:16 +01:00
parent 8ecb6c1721
commit 9b20997f58
2 changed files with 5 additions and 0 deletions

View File

@ -1283,6 +1283,7 @@ dev_reopen(struct dev *d)
pc = &d->ctl_list; pc = &d->ctl_list;
while ((c = *pc) != NULL) { while ((c = *pc) != NULL) {
if (c->addr >= CTLADDR_END) { if (c->addr >= CTLADDR_END) {
c->refs_mask &= ~CTL_DEVMASK;
if (c->refs_mask == 0) { if (c->refs_mask == 0) {
*pc = c->next; *pc = c->next;
xfree(c); xfree(c);
@ -2274,6 +2275,7 @@ dev_addctl(struct dev *d, char *gstr, int type, int addr,
c->dirty = 0; c->dirty = 0;
c->refs_mask = 0; c->refs_mask = 0;
for (i = 0; i < DEV_NCTLSLOT; i++) { for (i = 0; i < DEV_NCTLSLOT; i++) {
c->refs_mask |= CTL_DEVMASK;
if (d->ctlslot[i].ops != NULL) if (d->ctlslot[i].ops != NULL)
c->refs_mask |= 1 << i; c->refs_mask |= 1 << i;
} }
@ -2317,6 +2319,7 @@ dev_rmctl(struct dev *d, int addr)
log_puts("\n"); log_puts("\n");
} }
#endif #endif
c->refs_mask &= ~CTL_DEVMASK;
if (c->refs_mask != 0) if (c->refs_mask != 0)
return; return;
*pc = c->next; *pc = c->next;

View File

@ -134,6 +134,8 @@ struct ctl {
char str[CTL_NAMEMAX]; /* stream name */ char str[CTL_NAMEMAX]; /* stream name */
int unit; int unit;
} chan0, chan1; /* affected channels */ } chan0, chan1; /* affected channels */
#define CTL_DEVMASK (1 << 31)
#define CTL_SLOTMASK(i) (1 << (i))
unsigned int val_mask; unsigned int val_mask;
unsigned int desc_mask; unsigned int desc_mask;
unsigned int refs_mask; unsigned int refs_mask;