Make sure devices are properly closed in case of an error.
authorratchov <ratchov@openbsd.org>
Fri, 24 Apr 2020 11:33:28 +0000 (11:33 +0000)
committerratchov <ratchov@openbsd.org>
Fri, 24 Apr 2020 11:33:28 +0000 (11:33 +0000)
Fixes possible crashes if the contol device fails, while the audio
device continues to work.

usr.bin/sndiod/dev.c
usr.bin/sndiod/dev_sioctl.c
usr.bin/sndiod/siofile.c

index 740c8c7..9515664 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dev.c,v 1.70 2020/04/16 12:26:55 ratchov Exp $        */
+/*     $OpenBSD: dev.c,v 1.71 2020/04/24 11:33:28 ratchov Exp $        */
 /*
  * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
  *
@@ -1269,7 +1269,6 @@ int
 dev_reopen(struct dev *d)
 {
        struct slot *s;
-       struct ctl *c, **pc;
        long long pos;
        unsigned int pstate;
        int delta;
@@ -1323,23 +1322,8 @@ dev_reopen(struct dev *d)
                }
        }
 
-       /* remove controls of old device */
-       pc = &d->ctl_list;
-       while ((c = *pc) != NULL) {
-               if (c->addr >= CTLADDR_END) {
-                       c->refs_mask &= ~CTL_DEVMASK;
-                       if (c->refs_mask == 0) {
-                               *pc = c->next;
-                               xfree(c);
-                               continue;
-                       }
-                       c->type = CTL_NONE;
-                       c->desc_mask = ~0;
-               }
-               pc = &c->next;
-       }
-
-       /* add new device controls */
+       /* remove old controls and add new ones */
+       dev_sioctl_close(d);
        dev_sioctl_open(d);
 
        /* start the device if needed */
index 758d252..6785d9b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dev_sioctl.c,v 1.4 2020/04/16 12:26:55 ratchov Exp $  */
+/*     $OpenBSD: dev_sioctl.c,v 1.5 2020/04/24 11:33:28 ratchov Exp $  */
 /*
  * Copyright (c) 2014-2020 Alexandre Ratchov <alex@caoua.org>
  *
@@ -126,8 +126,6 @@ dev_sioctl_open(struct dev *d)
        }
        sioctl_ondesc(d->sioctl.hdl, dev_sioctl_ondesc, d);
        sioctl_onval(d->sioctl.hdl, dev_sioctl_onval, d);
-       d->sioctl.file = file_new(&dev_sioctl_ops, d, "mix",
-           sioctl_nfds(d->sioctl.hdl));
 }
 
 /*
@@ -136,9 +134,24 @@ dev_sioctl_open(struct dev *d)
 void
 dev_sioctl_close(struct dev *d)
 {
-       if (d->sioctl.hdl == NULL)
-               return;
-       file_del(d->sioctl.file);
+       struct ctl *c, **pc;
+
+       /* remove controls */
+       pc = &d->ctl_list;
+       while ((c = *pc) != NULL) {
+               if (c->addr >= CTLADDR_END) {
+                       c->refs_mask &= ~CTL_DEVMASK;
+                       if (c->refs_mask == 0) {
+                               *pc = c->next;
+                               xfree(c);
+                               continue;
+                       }
+                       c->type = CTL_NONE;
+                       c->desc_mask = ~0;
+               }
+               pc = &c->next;
+       }
+       dev_ctlsync(d);
 }
 
 int
@@ -207,4 +220,7 @@ dev_sioctl_hup(void *arg)
        struct dev *d = arg;
 
        dev_sioctl_close(d);
+       file_del(d->sioctl.file);
+       sioctl_close(d->sioctl.hdl);
+       d->sioctl.hdl = NULL;
 }
index c66941e..a33558c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: siofile.c,v 1.18 2020/02/26 13:53:58 ratchov Exp $    */
+/*     $OpenBSD: siofile.c,v 1.19 2020/04/24 11:33:28 ratchov Exp $    */
 /*
  * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
  *
@@ -42,6 +42,8 @@ int dev_sio_revents(void *, struct pollfd *);
 void dev_sio_run(void *);
 void dev_sio_hup(void *);
 
+extern struct fileops dev_sioctl_ops;
+
 struct fileops dev_sio_ops = {
        "sio",
        dev_sio_pollfd,
@@ -256,6 +258,10 @@ dev_sio_open(struct dev *d)
                d->mode &= ~MODE_REC;
        sio_onmove(d->sio.hdl, dev_sio_onmove, d);
        d->sio.file = file_new(&dev_sio_ops, d, "dev", sio_nfds(d->sio.hdl));
+       if (d->sioctl.hdl) {
+               d->sioctl.file = file_new(&dev_sioctl_ops, d, "mix",
+                   sioctl_nfds(d->sioctl.hdl));
+       }
        timo_set(&d->sio.watchdog, dev_sio_timeout, d);
        dev_sioctl_open(d);
        return 1;
@@ -321,8 +327,8 @@ dev_sio_reopen(struct dev *d)
        timo_del(&d->sio.watchdog);
        file_del(d->sio.file);
        sio_close(d->sio.hdl);
-       dev_sioctl_close(d);
        if (d->sioctl.hdl) {
+               file_del(d->sioctl.file);
                sioctl_close(d->sioctl.hdl);
                d->sioctl.hdl = NULL;
        }
@@ -341,6 +347,10 @@ dev_sio_reopen(struct dev *d)
        d->sio.hdl = hdl;
        d->sioctl.hdl = ctlhdl;
        d->sio.file = file_new(&dev_sio_ops, d, "dev", sio_nfds(hdl));
+       if (d->sioctl.hdl) {
+               d->sioctl.file = file_new(&dev_sioctl_ops, d, "mix",
+                   sioctl_nfds(ctlhdl));
+       }
        sio_onmove(hdl, dev_sio_onmove, d);
        return 1;
 bad_close:
@@ -364,6 +374,7 @@ dev_sio_close(struct dev *d)
        file_del(d->sio.file);
        sio_close(d->sio.hdl);
        if (d->sioctl.hdl) {
+               file_del(d->sioctl.file);
                sioctl_close(d->sioctl.hdl);
                d->sioctl.hdl = NULL;
        }