ref: 6d6c45d94e4a4a3eebf344f646027a6e939b45d2
parent: 4af9aa84c706c45398c4c7d1b9e96fa814a45dc0
author: Sigrid Haflínudóttir <[email protected]>
date: Wed Jun 17 14:21:07 EDT 2020
fix crash reported by qwx; harden player logic, print more useful info when something goes wrong
--- a/zuke.c
+++ b/zuke.c
@@ -404,7 +404,7 @@
player->ev = chancreate(sizeof(ulong), 0);
player->pcur = pcur;
- threadcreate(playerthread, player, mainstacksize);
+ threadcreate(playerthread, player, 4096);
if(playerret(player) < 0)
return nil;
@@ -431,7 +431,8 @@
Ioproc *io;
Image *thiscover;
ulong c;
- int p[2], fd, pid, n, noinit, trycoverload;
+ int p[2], fd, pid, noinit, trycoverload;
+ long n, r;
u64int bytesfrom, bf;
Meta *cur;
@@ -481,10 +482,11 @@
if(!noinit){
sendul(player->ev, Evready);
buf = malloc(Relbufsz);
- io = ioproc();
- n = ioreadn(io, p[1], buf, Relbufsz);
- c = recvul(player->ctl);
- if(c != Cstart)
+ if((io = ioproc()) == nil)
+ sysfatal("player: %r");
+ if((n = ioreadn(io, p[1], buf, Relbufsz)) < 0)
+ fprint(2, "player: %r\n");
+ if(n < 1 || recv(player->ctl, &c) < 0 || c != Cstart)
goto freeplayer;
byteswritten = iowrite(io, audio, buf, n);
bytesfrom = 0;
@@ -501,7 +503,7 @@
if(bytesfrom > byteswritten && n > bytesfrom-byteswritten)
n = bytesfrom-byteswritten;
n = ioreadn(io, p[1], buf, n);
- if(n < 0)
+ if(n <= 0)
break;
thiscover = nil;
@@ -511,36 +513,36 @@
redraw(1);
player->img = nil;
}
- c = nbrecvul(player->ctl);
bf = bytesfrom != 0 ? bytesfrom : byteswritten;
- if(c == Cstop || c == -1)
+ r = nbrecv(player->ctl, &c);
+ if(r < 0){
goto stop;
- if(c == Ctoggle){
- c = recvul(player->ctl);
- if(c == Cstop)
+ }else if(r != 0){
+ if(c == Ctoggle){
+ if(recv(player->ctl, &c) < 0 || c == Cstop)
+ goto stop;
+ }else if(c == Cforward){
+ bytesfrom = bf + Seekbytes;
+ }else if(c == Cforwardfast){
+ bytesfrom = bf + Seekbytesfast;
+ }else if(c == Cbackward){ /* to seek backwards we need to restart playback */
+ bytesfrom = bf >= Seekbytes ? bf - Seekbytes : 0;
+ n = 0; /* not an error */
+ break;
+ }else if(c == Cbackwardfast){
+ bytesfrom = bf >= Seekbytesfast ? bf - Seekbytesfast : 0;
+ n = 0; /* not an error */
+ break;
+ }else{ /* Cstop */
goto stop;
- }else if(c == Cforward){
- bytesfrom = bf + Seekbytes;
- }else if(c == Cforwardfast){
- bytesfrom = bf + Seekbytesfast;
- }else if(c == Cbackward){ /* to seek backwards we need to restart playback */
- bytesfrom = bf >= Seekbytes ? bf - Seekbytes : 0;
- n = 0; /* not an error */
- break;
- }else if(c == Cbackwardfast){
- bytesfrom = bf >= Seekbytesfast ? bf - Seekbytesfast : 0;
- n = 0; /* not an error */
- break;
+ }
}
- c = 0;
if(bytesfrom <= byteswritten){
if(bytesfrom == byteswritten)
bytesfrom = 0;
- if(iowrite(io, audio, buf, n) != n){
- fprint(2, "failed to write %d bytes: %r\n", n);
- break;
- }
+ if(iowrite(io, audio, buf, n) != n)
+ fprint(2, "player: %r\n");
if(trycoverload && byteswritten >= Bps){
player->img = chancreate(sizeof(Image*), 0);
proccreate(coverload, player, 4096);
@@ -554,6 +556,7 @@
if(n < 1){ /* seeking backwards or end of the song */
close(p[1]);
+ p[1] = -1;
if(c != Cbackward && c != Cbackwardfast){
playercurr = nil;
playercurr = newplayer((player->pcur+1) % plnum, 1);
@@ -567,20 +570,19 @@
if(player->img != nil)
freeimage(recvp(player->img));
freeplayer:
+ chanfree(player->ctl);
+ chanfree(player->ev);
+ if(pid >= 0)
+ postnote(PNGROUP, pid, "interrupt");
+ closeioproc(io);
+ if(p[1] >= 0)
+ close(p[1]);
if(player == playercurr)
playercurr = nil;
if(player == playernext)
playernext = nil;
- chanclose(player->ctl);
- chanclose(player->ev);
- chanfree(player->ctl);
- chanfree(player->ev);
- close(p[1]);
- closeioproc(io);
free(buf);
free(player);
- if(pid >= 0)
- postnote(PNGROUP, pid, "interrupt");
threadexits(nil);
}