mirror of https://github.com/ericonr/sndio.git
On error, drop clients and close the device only if it's still open
Fixes crashes when USB devices are disconnected, caused by an attempt to close the already closed device: it was closed once when its ref counter drops to zero (after the last client is disconnected) and once with an explicit call to dev_close() on the error code-path. The same pattern was used for MIDI ports, it's fixed as well.
This commit is contained in:
parent
c531dda0ad
commit
f29a76bc19
|
@ -60,7 +60,6 @@ struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int,
|
|||
void dev_adjpar(struct dev *, int, int, int);
|
||||
int dev_allocbufs(struct dev *);
|
||||
int dev_open(struct dev *);
|
||||
void dev_exitall(struct dev *);
|
||||
void dev_freebufs(struct dev *);
|
||||
void dev_close(struct dev *);
|
||||
int dev_ref(struct dev *);
|
||||
|
@ -1194,10 +1193,10 @@ dev_open(struct dev *d)
|
|||
}
|
||||
|
||||
/*
|
||||
* Force all slots to exit
|
||||
* Force all slots to exit and close device, called after an error
|
||||
*/
|
||||
void
|
||||
dev_exitall(struct dev *d)
|
||||
dev_abort(struct dev *d)
|
||||
{
|
||||
int i;
|
||||
struct slot *s;
|
||||
|
@ -1215,6 +1214,9 @@ dev_exitall(struct dev *d)
|
|||
c->ops->exit(c->arg);
|
||||
c->ops = NULL;
|
||||
}
|
||||
|
||||
if (d->pstate != DEV_CFG)
|
||||
dev_close(d);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1250,7 +1252,6 @@ dev_close(struct dev *d)
|
|||
{
|
||||
struct ctl *c;
|
||||
|
||||
dev_exitall(d);
|
||||
d->pstate = DEV_CFG;
|
||||
dev_sio_close(d);
|
||||
dev_freebufs(d);
|
||||
|
|
|
@ -260,7 +260,7 @@ struct dev {
|
|||
extern struct dev *dev_list;
|
||||
|
||||
void dev_log(struct dev *);
|
||||
void dev_close(struct dev *);
|
||||
void dev_abort(struct dev *);
|
||||
int dev_reopen(struct dev *);
|
||||
struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int,
|
||||
unsigned int, unsigned int, unsigned int, unsigned int);
|
||||
|
|
|
@ -564,7 +564,7 @@ port_open(struct port *c)
|
|||
}
|
||||
|
||||
void
|
||||
port_exitall(struct port *c)
|
||||
port_abort(struct port *c)
|
||||
{
|
||||
int i;
|
||||
struct midi *ep;
|
||||
|
@ -575,6 +575,9 @@ port_exitall(struct port *c)
|
|||
(c->midi->txmask & ep->self))
|
||||
ep->ops->exit(ep->arg);
|
||||
}
|
||||
|
||||
if (c->state != PORT_CFG)
|
||||
port_close(c);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -589,8 +592,6 @@ port_close(struct port *c)
|
|||
#endif
|
||||
c->state = PORT_CFG;
|
||||
port_mio_close(c);
|
||||
|
||||
port_exitall(c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,5 +124,6 @@ void port_done(struct port *);
|
|||
void port_drain(struct port *);
|
||||
int port_close(struct port *);
|
||||
int port_reopen(struct port *);
|
||||
void port_abort(struct port *);
|
||||
|
||||
#endif /* !defined(MIDI_H) */
|
||||
|
|
|
@ -187,5 +187,5 @@ port_mio_hup(void *arg)
|
|||
struct port *p = arg;
|
||||
|
||||
if (!port_reopen(p))
|
||||
port_close(p);
|
||||
port_abort(p);
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ dev_sio_timeout(void *arg)
|
|||
|
||||
dev_log(d);
|
||||
log_puts(": watchdog timeout\n");
|
||||
dev_close(d);
|
||||
dev_abort(d);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -640,5 +640,5 @@ dev_sio_hup(void *arg)
|
|||
}
|
||||
#endif
|
||||
if (!dev_reopen(d))
|
||||
dev_close(d);
|
||||
dev_abort(d);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue