Hi, tail -r has two memory leaks when handling non-regular files. You can easily see memory usage increasing with commands like
$ mknod pipe p $ tail -r pipe pipe pipe > /dev/null And then writing a large file into the pipe three times. top shows the memory usage of tail increasing with each consecutive read. The obvious memory leak is at the end of reverse(): the doubly linked list (actually circular list) is never freed. To fix this, I break the circle and iterate through it, freeing items until I hit NULL. The less obvious one is in an error path. If tail fails to allocate an item (tl) or space for its content (tl->l), it won't simply err() out but tries to recover. Yet, it doesn't free tl if allocation of tl->l failed. Tobias Index: reverse.c =================================================================== RCS file: /cvs/src/usr.bin/tail/reverse.c,v retrieving revision 1.19 diff -u -p -U4 -r1.19 reverse.c --- reverse.c 27 Oct 2009 23:59:44 -0000 1.19 +++ reverse.c 26 Mar 2015 22:31:38 -0000 @@ -183,8 +183,10 @@ r_buf(FILE *fp) if (enomem || (tl = malloc(sizeof(BF))) == NULL || (tl->l = malloc(BSZ)) == NULL) { if (!mark) err(1, NULL); + if (!enomem) + free(tl); tl = enomem ? tl->next : mark; enomem += tl->len; } else if (mark) { tl->next = mark; @@ -258,6 +260,14 @@ r_buf(FILE *fp) } while ((tl = tl->next)->len) { WR(tl->l, tl->len); tl->len = 0; + } + + tl->prev->next = NULL; + while (tl != NULL) { + tr = tl->next; + free(tl->l); + free(tl); + tl = tr; } }