tFix a handful of small one-time memory leaks in vbackup, and one per-package memory leak (in writethread). - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 6fc7da3c529ca7c610e8172f5b02980c75597dd5
 (DIR) parent 067d852abe242ee1d267bcc0d652cd6bb31b7e17
 (HTM) Author: rsc <devnull@localhost>
       Date:   Thu, 19 Oct 2006 21:58:59 +0000
       
       Fix a handful of small one-time memory leaks in vbackup,
       and one per-package memory leak (in writethread).
       
       Diffstat:
         M include/venti.h                     |       3 +++
         M src/cmd/vbackup/queue.c             |       6 ++++++
         M src/cmd/vbackup/queue.h             |       1 +
         M src/cmd/vbackup/vbackup.c           |      21 +++++++++++++++++++++
         M src/libdiskfs/cache.c               |       2 +-
         M src/libdiskfs/ffs.c                 |       1 +
         M src/libventi/cache.c                |      13 ++++++++++---
         M src/libventi/client.c               |       9 +++++++++
         M src/libventi/conn.c                 |      12 ++++++++----
         M src/libventi/fcall.c                |       1 +
         M src/libventi/file.c                 |       7 ++++++-
         M src/libventi/hangup.c               |       5 +++++
         M src/libventi/packet.c               |       1 -
         M src/libventi/queue.c                |      14 ++++++++++++++
         M src/libventi/queue.h                |       1 +
         M src/libventi/rpc.c                  |       6 +++++-
         M src/libventi/send.c                 |       4 ++--
       
       17 files changed, 94 insertions(+), 13 deletions(-)
       ---
 (DIR) diff --git a/include/venti.h b/include/venti.h
       t@@ -348,6 +348,8 @@ Packet *vtrecv(VtConn*);
        int vtversion(VtConn *z);
        void vtdebug(VtConn *z, char*, ...);
        void vthangup(VtConn *z);
       +int vtgoodbye(VtConn *z);
       +
        /* #pragma varargck argpos vtdebug 2 */
        
        /* server */
       t@@ -412,6 +414,7 @@ struct VtBlock
                u32int        used;
                u32int        used2;
                u32int        addr;
       +        uintptr        pc;
        };
        
        u32int vtglobaltolocal(uchar[VtScoreSize]);
 (DIR) diff --git a/src/cmd/vbackup/queue.c b/src/cmd/vbackup/queue.c
       t@@ -62,3 +62,9 @@ qclose(Queue *q)
                rwakeup(&q->r);
                qunlock(&q->lk);
        }
       +
       +void
       +qfree(Queue *q)
       +{
       +        vtfree(q);
       +}
 (DIR) diff --git a/src/cmd/vbackup/queue.h b/src/cmd/vbackup/queue.h
       t@@ -20,3 +20,4 @@ Queue        *qalloc(void);
        void        qclose(Queue*);
        Block        *qread(Queue*, u32int*);
        void        qwrite(Queue*, Block*, u32int);
       +void        qfree(Queue*);
 (DIR) diff --git a/src/cmd/vbackup/vbackup.c b/src/cmd/vbackup/vbackup.c
       t@@ -284,6 +284,9 @@ threadmain(int argc, char **argv)
                 * wait for processes to finish
                 */
                wlock(&endlk);
       +        
       +        qfree(qcmp);
       +        qfree(qventi);
        
                if(statustime)
                        print("# %T procs exited: %d blocks changed, %d read, %d written, %d skipped, %d copied\n",
       t@@ -297,6 +300,8 @@ threadmain(int argc, char **argv)
                        sysfatal("vtfileflush: %r");
                if(vtfilegetentry(vfile, &e) < 0)
                        sysfatal("vtfilegetentry: %r");
       +        vtfileunlock(vfile);
       +        vtfileclose(vfile);
        
                b = vtcacheallocblock(c, VtDirType);
                if(b == nil)
       t@@ -336,6 +341,19 @@ threadmain(int argc, char **argv)
                        sysfatal("vtsync: %r");
                if(statustime)
                        print("# %T synced\n");
       +        
       +        fsysclose(fsys);
       +        diskclose(disk);
       +        vtcachefree(zcache);
       +        vtgoodbye(z);
       +        // Leak here, because I can't seem to make
       +        // the vtrecvproc exit.
       +        // vtfreeconn(z);
       +        free(tmpnam);
       +        z = nil;
       +        zcache = nil;
       +        fsys = nil;
       +        disk = nil;
                threadexitsall(nil);
        }
        
       t@@ -416,6 +434,7 @@ writethread(void *v)
                        }
                        if(vtwritepacket(z, wr.score, wr.type, wr.p) < 0)
                                sysfatal("vtwritepacket: %r");
       +                packetfree(wr.p);
                }
        }
        
       t@@ -472,6 +491,7 @@ ventiproc(void *dummy)
                vtcachesetwrite(zcache, nil);
                for(i=0; i<nwritethread; i++)
                        send(writechan, nil);
       +        chanfree(writechan);
                if(statustime)
                        print("# %T venti proc exiting - nsend %d nrecv %d\n", nsend, nrecv);
                runlock(&endlk);
       t@@ -534,6 +554,7 @@ mountplace(char *dev)
                if(threadspawnl(fd, "sh", "sh", "-c", cmd, nil) < 0)
                        sysfatal("exec mount|awk (to find mtpt of %s): %r", dev);
                /* threadspawnl closed p[1] */
       +        free(cmd);
                n = readn(p[0], buf, sizeof buf-1);
                close(p[0]);
                if(n <= 0)
 (DIR) diff --git a/src/libdiskfs/cache.c b/src/libdiskfs/cache.c
       t@@ -5,7 +5,7 @@
        /*
         * Disk cache.  Caches by offset, so higher levels have 
         * to deal with alignment issues (if we get asked for the
       - * blocks at offsets 0 and 1, we'll do two reads.
       + * blocks at offsets 0 and 1, we'll do two reads).
         */
        
        typedef struct DiskCache DiskCache;
 (DIR) diff --git a/src/libdiskfs/ffs.c b/src/libdiskfs/ffs.c
       t@@ -46,6 +46,7 @@ fsysopenffs(Disk *disk)
                fsys->_readfile = ffsreadfile;
                fsys->_readlink = ffsreadlink;
                fsys->_readdir = ffsreaddir;
       +        fsys->_close = ffsclose;
                fsys->fileblock = ffsxfileblock;
        
                if(ffssync(fsys) < 0)
 (DIR) diff --git a/src/libventi/cache.c b/src/libventi/cache.c
       t@@ -167,7 +167,7 @@ fprint(2, "cachecheck: nheap %d refed %d nblocks %d\n", c->nheap, refed, c->nblo
                for(i = 0; i < c->nblock; i++){
                        b = &c->block[i];
                        if(b->ref){
       -if(1)fprint(2, "a=%ud %V ref=%d\n", b->addr, b->score, b->ref);
       +if(1)fprint(2, "a=%ud %V ref=%d pc=%#lux\n", b->addr, b->score, b->ref, (ulong)b->pc);
                                refed++;
                        }
                }
       t@@ -333,6 +333,7 @@ vtcachelocal(VtCache *c, u32int addr, int type)
        
                qlock(&b->lk);
                b->nlock = 1;
       +        b->pc = getcallerpc(&c);
                return b;
        }
        
       t@@ -352,7 +353,7 @@ vtcacheallocblock(VtCache *c, int type)
        
                qlock(&b->lk);
                b->nlock = 1;
       -
       +        b->pc = getcallerpc(&b);
                return b;
        }
        
       t@@ -374,7 +375,10 @@ vtcacheglobal(VtCache *c, uchar score[VtScoreSize], int type)
                if(addr != NilBlock){
                        if(vttracelevel)
                                fprint(2, "vtcacheglobal %V %d => local\n", score, type);
       -                return vtcachelocal(c, addr, type);
       +                b = vtcachelocal(c, addr, type);
       +                if(b)
       +                        b->pc = getcallerpc(&c);
       +                return b;
                }
        
                h = (u32int)(score[0]|(score[1]<<8)|(score[2]<<16)|(score[3]<<24)) % c->nhash;
       t@@ -404,6 +408,7 @@ vtcacheglobal(VtCache *c, uchar score[VtScoreSize], int type)
                        }
                        if(vttracelevel)
                                fprint(2, "vtcacheglobal %V %d => found in cache; returning\n", score, type);
       +                b->pc = getcallerpc(&c);
                        return b;
                }
        
       t@@ -451,6 +456,7 @@ vtcacheglobal(VtCache *c, uchar score[VtScoreSize], int type)
                b->nlock = 1;
                if(vttracelevel)
                        fprint(2, "vtcacheglobal %V %d => loaded into cache; returning\n", score, type);
       +        b->pc = getcallerpc(&b);
                return b;
        }
        
       t@@ -573,6 +579,7 @@ vtblockcopy(VtBlock *b)
                }
                memmove(bb->data, b->data, b->c->blocksize);
                vtblockput(b);
       +        bb->pc = getcallerpc(&b);
                return bb;
        }
        
 (DIR) diff --git a/src/libventi/client.c b/src/libventi/client.c
       t@@ -169,3 +169,12 @@ vtconnect(VtConn *z)
                return 0;
        }
        
       +int
       +vtgoodbye(VtConn *z)
       +{
       +        VtFcall tx, rx;
       +        
       +        tx.msgtype = VtTgoodbye;
       +        vtfcallrpc(z, &tx, &rx);        /* always fails: no VtRgoodbye */
       +        return 0;
       +}
 (DIR) diff --git a/src/libventi/conn.c b/src/libventi/conn.c
       t@@ -32,15 +32,19 @@ vtfreeconn(VtConn *z)
        {
                vthangup(z);
                qlock(&z->lk);
       -        for(;;){
       +        /*
       +         * Wait for send and recv procs to notice
       +         * the hangup and clear out the queues.
       +         */
       +        while(z->readq || z->writeq){
                        if(z->readq)
                                _vtqhangup(z->readq);
       -                else if(z->writeq)
       +                if(z->writeq)
                                _vtqhangup(z->writeq);
       -                else
       -                        break;
                        rsleep(&z->rpcfork);
                }
                packetfree(z->part);
       +        vtfree(z->version);
       +        vtfree(z->sid);
                vtfree(z);
        }
 (DIR) diff --git a/src/libventi/fcall.c b/src/libventi/fcall.c
       t@@ -205,6 +205,7 @@ vtfcallunpack(VtFcall *f, Packet *p)
        
        Err:
                werrstr("bad packet");
       +        vtfcallclear(f);
                return -1;
        }
        
 (DIR) diff --git a/src/libventi/file.c b/src/libventi/file.c
       t@@ -699,7 +699,7 @@ vtfileblock(VtFile *r, u32int bn, int mode)
        
                i = mkindices(&e, bn, index);
                if(i < 0)
       -                return nil;
       +                goto Err;
                if(i > DEPTH(e.type)){
                        if(mode == VtOREAD){
                                werrstr("bad address 0x%lux", (ulong)bn);
       t@@ -726,6 +726,7 @@ assert(b->type == VtDirType);
                        vtblockput(b);
                        b = bb;
                }
       +        b->pc = getcallerpc(&r);
                return b;
        Err:
                vtblockput(b);
       t@@ -833,6 +834,7 @@ fileloadblock(VtFile *r, int mode)
                                b = vtcacheglobal(r->c, r->score, VtDirType);
                                if(b == nil)
                                        return nil;
       +                        b->pc = getcallerpc(&r);
                                return b;
                        }
                        assert(r->parent != nil);
       t@@ -902,6 +904,7 @@ vtfilelock(VtFile *r, int mode)
                 */
                assert(r->b == nil);
                r->b = b;
       +        b->pc = getcallerpc(&r);
                return 0;
        }
        
       t@@ -948,6 +951,8 @@ vtfilelock2(VtFile *r, VtFile *rr, int mode)
                 */
                r->b = b;
                rr->b = bb;
       +        b->pc = getcallerpc(&r);
       +        bb->pc = getcallerpc(&r);
                return 0;
        }
        
 (DIR) diff --git a/src/libventi/hangup.c b/src/libventi/hangup.c
       t@@ -1,4 +1,5 @@
        #include <u.h>
       +#include <sys/socket.h>
        #include <libc.h>
        #include <venti.h>
        #include "queue.h"
       t@@ -8,6 +9,9 @@ vthangup(VtConn *z)
        {
                qlock(&z->lk);
                z->state = VtStateClosed;
       +        /* try to make the read in vtsendproc fail */
       +        shutdown(SHUT_WR, z->infd);
       +        shutdown(SHUT_WR, z->outfd);
                if(z->infd >= 0)
                        close(z->infd);
                if(z->outfd >= 0 && z->outfd != z->infd)
       t@@ -20,3 +24,4 @@ vthangup(VtConn *z)
                        _vtqhangup(z->readq);
                qunlock(&z->lk);
        }
       +
 (DIR) diff --git a/src/libventi/packet.c b/src/libventi/packet.c
       t@@ -756,7 +756,6 @@ packetcmp(Packet *pkt0, Packet *pkt1)
                        }
                }
        }
       -        
        
        static Frag *
        fragalloc(Packet *p, int n, int pos, Frag *next)
 (DIR) diff --git a/src/libventi/queue.c b/src/libventi/queue.c
       t@@ -29,6 +29,20 @@ _vtqalloc(void)
                return q;
        }
        
       +void
       +_vtqfree(Queue *q)
       +{
       +        Qel *e;
       +        
       +        /* Leaks the pointers e->p! */
       +        while(q->head){
       +                e = q->head;
       +                q->head = e->next;
       +                free(e);
       +        }
       +        free(q);
       +}
       +
        int
        _vtqsend(Queue *q, void *p)
        {
 (DIR) diff --git a/src/libventi/queue.h b/src/libventi/queue.h
       t@@ -4,3 +4,4 @@ int _vtqsend(Queue*, void*);
        void *_vtqrecv(Queue*);
        void _vtqhangup(Queue*);
        void *_vtnbqrecv(Queue*);
       +void _vtqfree(Queue*);
 (DIR) diff --git a/src/libventi/rpc.c b/src/libventi/rpc.c
       t@@ -59,12 +59,15 @@ _vtrpc(VtConn *z, Packet *p, VtFcall *tx)
                if(top == buf){
                        werrstr("first two bytes must be in same packet fragment");
                        packetfree(p);
       +                vtfree(r);
                        return nil;
                }
                top[1] = tag;
                qunlock(&z->lk);
       -        if(vtsend(z, p) < 0)
       +        if(vtsend(z, p) < 0){
       +                vtfree(r);
                        return nil;
       +        }
        
                qlock(&z->lk);
                /* wait for the muxer to give us our packet */
       t@@ -85,6 +88,7 @@ _vtrpc(VtConn *z, Packet *p, VtFcall *tx)
                                if((p = vtrecv(z)) == nil){
                                        werrstr("unexpected eof on venti connection");
                                        z->muxer = 0;
       +                                vtfree(r);
                                        return nil;
                                }
                                qlock(&z->lk);
 (DIR) diff --git a/src/libventi/send.c b/src/libventi/send.c
       t@@ -147,7 +147,7 @@ vtrecvproc(void *v)
                _vtqhangup(q);
                while((p = _vtnbqrecv(q)) != nil)
                        packetfree(p);
       -        vtfree(q);
       +        _vtqfree(q);
                z->readq = nil;
                rwakeup(&z->rpcfork);
                qunlock(&z->lk);
       t@@ -178,7 +178,7 @@ vtsendproc(void *v)
                _vtqhangup(q);
                while((p = _vtnbqrecv(q)) != nil)
                        packetfree(p);
       -        vtfree(q);
       +        _vtqfree(q);
                z->writeq = nil;
                rwakeup(&z->rpcfork);
                qunlock(&z->lk);