11.13

--- tiny.origin.c	2021-02-25 07:26:33.302592754 +0000
+++ tiny.13.c	2021-02-25 07:26:33.302592754 +0000
@@ -13,6 +13,17 @@
 void clienterror(int fd, char *cause, char *errnum,
     char *shortmsg, char *longmsg);
 
+// improved rio written
+void Im_rio_writen(int fd, void *usrbuf, size_t n) {
+  if (rio_writen(fd, usrbuf, n) != n) {
+    if (errno == EPIPE)
+      fprintf(stderr, "EPIPE error");
+
+    fprintf(stderr, "%s ", strerror(errno));
+    unix_error("client side has ended connection");
+  }
+}
+
 int main(int argc, char **argv)
 {
   int listenfd, connfd;
@@ -26,6 +37,9 @@
     exit(1);
   }
 
+  if (Signal(SIGPIPE, SIG_IGN) == SIG_ERR)
+    unix_error("mask signal pipe error");
+
   listenfd = Open_listenfd(argv[1]);
   while (1) {
     clientlen = sizeof(clientaddr);
@@ -148,7 +162,7 @@
   sprintf(buf, "%sConnection: close\r\n", buf);
   sprintf(buf, "%sContent-length: %d\r\n", buf, filesize);
   sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype);
-  Rio_writen(fd, buf, strlen(buf));       //line:netp:servestatic:endserve
+  Im_rio_writen(fd, buf, strlen(buf));       //line:netp:servestatic:endserve
   printf("Response headers:\n");
   printf("%s", buf);
 
@@ -156,7 +170,7 @@
   srcfd = Open(filename, O_RDONLY, 0);    //line:netp:servestatic:open
   srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);//line:netp:servestatic:mmap
   Close(srcfd);                           //line:netp:servestatic:close
-  Rio_writen(fd, srcp, filesize);         //line:netp:servestatic:write
+  Im_rio_writen(fd, srcp, filesize);         //line:netp:servestatic:write
   Munmap(srcp, filesize);                 //line:netp:servestatic:munmap
 }
 
@@ -186,11 +200,13 @@
 
   /* Return first part of HTTP response */
   sprintf(buf, "HTTP/1.0 200 OK\r\n");
-  Rio_writen(fd, buf, strlen(buf));
+  Im_rio_writen(fd, buf, strlen(buf));
   sprintf(buf, "Server: Tiny Web Server\r\n");
-  Rio_writen(fd, buf, strlen(buf));
+  Im_rio_writen(fd, buf, strlen(buf));
 
   if (Fork() == 0) { /* Child */ //line:netp:servedynamic:fork
+    if (Signal(SIGPIPE, SIG_DFL) == SIG_ERR)
+      unix_error("unmask signal pipe error");
     /* Real server would set all CGI vars here */
     setenv("QUERY_STRING", cgiargs, 1); //line:netp:servedynamic:setenv
     Dup2(fd, STDOUT_FILENO);         /* Redirect stdout to client */ //line:netp:servedynamic:dup2
@@ -216,10 +232,10 @@
 
   /* Print the HTTP response */
   sprintf(buf, "HTTP/1.0 %s %s\r\n", errnum, shortmsg);
-  Rio_writen(fd, buf, strlen(buf));
+  Im_rio_writen(fd, buf, strlen(buf));
   sprintf(buf, "Content-type: text/html\r\n");
-  Rio_writen(fd, buf, strlen(buf));
+  Im_rio_writen(fd, buf, strlen(buf));
   sprintf(buf, "Content-length: %d\r\n\r\n", (int)strlen(body));
-  Rio_writen(fd, buf, strlen(buf));
-  Rio_writen(fd, body, strlen(body));
+  Im_rio_writen(fd, buf, strlen(buf));
+  Im_rio_writen(fd, body, strlen(body));
 }

ignore SIGPIPE and show more friendly errer message.

unmask SIGPIPE, leave child process to handle it.

comments powered by Disqus