shithub: zuke

Download patch

ref: 6d6c45d94e4a4a3eebf344f646027a6e939b45d2
parent: 4af9aa84c706c45398c4c7d1b9e96fa814a45dc0
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
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);
 }