Ignore:
Timestamp:
Oct 31, 2007, 6:10:55 PM (15 years ago)
Author:
charles
Message:

"corruption" fix part 3: cleanup. remove unneeded possible points of failure.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/fdlimit.c

    r3650 r3666  
    2525#include <assert.h>
    2626#include <errno.h>
     27#include <inttypes.h>
    2728#include <stdio.h>
    2829#include <stdlib.h>
     
    4344#include "transmission.h"
    4445#include "trcompat.h"
     46#include "list.h"
    4547#include "net.h"
    4648#include "platform.h"
    4749#include "utils.h"
     50
     51#if SIZEOF_VOIDP==8
     52#define TR_UINT_TO_PTR(i) (void*)((uint64_t)i)
     53#else
     54#define TR_UINT_TO_PTR(i) ((void*)((uint32_t)i))
     55#endif
    4856
    4957/**
     
    8290enum
    8391{
    84     TR_MAX_OPEN_FILES = 16, /* That is, real files, not sockets */
     92    TR_MAX_OPEN_FILES = 16, /* real files, not sockets */
    8593
    8694    TR_RESERVED_FDS   = 16 /* sockets reserved for tracker connections */
     
    92100    unsigned int  isWritable : 1;
    93101    char          filename[MAX_PATH_LENGTH];
    94     int           file;
     102    int           fd;
    95103    uint64_t      date;
    96104};
     
    118126{
    119127    struct tr_openfile * file = &gFd->open[i];
    120     struct stat sb;
    121128    char * dir;
    122129    int flags;
     
    131138    }
    132139
    133     /* Make sure the parent folder exists */
    134     if( stat( dir, &sb ) || !S_ISDIR( sb.st_mode ) ) {
    135         free( dir );
    136         return TR_ERROR_IO_PARENT;
    137     }
    138 
    139     errno = 0;
    140     flags = 0;
     140    /* open the file */
     141    flags = write ? (O_RDWR | O_CREAT) : O_RDONLY;
    141142#ifdef WIN32
    142143    flags |= O_BINARY;
    143144#endif
    144     flags |= write ? (O_RDWR | O_CREAT) : O_RDONLY;
    145     file->file = open( filename, flags, 0666 );
     145    errno = 0;
     146    file->fd = open( filename, flags, 0600 );
    146147    free( dir );
    147     if( write && ( file->file < 0 ) )
    148     {
    149         const int ret = tr_ioErrorFromErrno();
    150         if( errno )
     148    if( file->fd < 0 ) {
     149        if( errno ) {
    151150            tr_err( "Couldn't open '%s': %s", filename, strerror(errno) );
    152         else
     151            return tr_ioErrorFromErrno();
     152        } else {
    153153            tr_err( "Couldn't open '%s'", filename );
    154         return ret;
     154            return TR_ERROR_IO_OTHER;
     155        }
    155156    }
    156157
     
    161162fileIsOpen( const struct tr_openfile * o )
    162163{
    163     return o->file >= 0;
     164    return o->fd >= 0;
    164165}
    165166
     
    167168TrCloseFile( int i )
    168169{
    169     struct tr_openfile * file = &gFd->open[i];
     170    struct tr_openfile * o = &gFd->open[i];
    170171
    171172    assert( i >= 0 );
    172173    assert( i < TR_MAX_OPEN_FILES );
    173     assert( fileIsOpen( file ) );
    174 
    175     dbgmsg( "closing %s in slot %d writable %c",
    176             file->filename, i, file->isWritable?'y':'n' );
    177     close( file->file );
    178     file->file = -1;
    179     file->isCheckedOut = 0;
     174    assert( fileIsOpen( o ) );
     175
     176    dbgmsg( "closing slot #%d, %s", i, o->filename );
     177    close( o->fd );
     178    o->fd = -1;
     179    o->isCheckedOut = 0;
    180180    tr_condSignal( gFd->cond );
    181181}
     
    192192    int i, winner;
    193193    struct tr_openfile * o;
     194
     195    assert( filename && *filename );
     196    assert( write==0 || write==1 );
    194197
    195198    dbgmsg( "looking for file '%s', writable %c", filename, write?'y':'n' );
     
    211214            dbgmsg( "found it!  it's open, but checked out.  waiting..." );
    212215            tr_condWait( gFd->cond, gFd->lock );
    213             i = -1;
     216            i = -1; /* reloop */
    214217            continue;
    215218        }
     
    218221            dbgmsg( "found it!  it's open and available, but isn't writable. closing..." );
    219222            TrCloseFile( i );
    220             continue;
     223            break;
    221224        }
    222225
     
    243246            }
    244247
    245             if( o->date < date ) {
     248            if( date > o->date ) {
     249                date = o->date;
    246250                winner = i;
    247                 date = o->date;
    248251            }
    249252        }
     
    272275
    273276        dbgmsg( "opened '%s' in slot %d, write %c", filename, winner, write?'y':'n' );
    274         strlcpy( gFd->open[winner].filename, filename, MAX_PATH_LENGTH );
    275         gFd->open[winner].isWritable = write;
     277        strlcpy( o->filename, filename, sizeof( o->filename ) );
     278        o->isWritable = write;
    276279    }
    277280
    278281    dbgmsg( "checking out '%s' in slot %d", filename, winner );
    279     gFd->open[winner].isCheckedOut = 1;
    280     gFd->open[winner].date = tr_date();
     282    o->isCheckedOut = 1;
     283    o->date = tr_date();
    281284    tr_lockUnlock( gFd->lock );
    282     return gFd->open[winner].file;
     285    return o->fd;
    283286}
    284287
     
    291294    for( i=0; i<TR_MAX_OPEN_FILES; ++i ) {
    292295        struct tr_openfile * o = &gFd->open[i];
    293         if( o->file == file ) {
     296        if( o->fd == file ) {
    294297            dbgmsg( "releasing file '%s' in slot #%d", o->filename, i );
    295298            if( o->isWritable )
    296                 fsync( o->file ); /* fflush */
     299                fsync( o->fd ); /* fflush */
    297300            o->isCheckedOut = 0;
    298301            break;
     
    310313***/
    311314
    312 struct tr_socket
    313 {
    314     int socket;
    315     int priority;
    316 };
    317 
    318 /* Remember the priority of every socket we open, so that we can keep
    319  * track of how many reserved file descriptors we are using */
    320 static struct tr_socket * gSockets = NULL;
    321 static int gSocketsSize = 0;
    322 static int gSocketsCount = 0;
     315static tr_list * reservedSockets = NULL;
    323316
    324317static void
    325 SocketSetPriority( int s, int priority )
    326 {
    327     if( gSocketsSize <= gSocketsCount ) {
    328         gSocketsSize += 64;
    329         gSockets = tr_renew( struct tr_socket, gSockets, gSocketsSize );
    330     }
    331 
    332     gSockets[gSocketsCount].socket = s;
    333     gSockets[gSocketsCount].priority = priority;
    334     ++gSocketsCount;
     318setSocketPriority( int fd, int isReserved )
     319{
     320    if( isReserved )
     321        tr_list_append( &reservedSockets, TR_UINT_TO_PTR(fd) );
    335322}
    336323
    337324static int
    338 SocketGetPriority( int s )
    339 {
    340     int i, ret;
    341 
    342     for( i=0; i<gSocketsCount; ++i )
    343         if( gSockets[i].socket == s )
    344             break;
    345 
    346     if( i >= gSocketsCount ) {
    347         tr_err( "could not find that socket (%d)!", s );
    348         return -1;
    349     }
    350 
    351     ret = gSockets[i].priority;
    352     gSocketsCount--;
    353     memmove( &gSockets[i], &gSockets[i+1],
    354             ( gSocketsCount - i ) * sizeof( struct tr_socket ) );
    355     return ret;
     325socketWasReserved( int fd )
     326{
     327    return tr_list_remove_data( &reservedSockets, TR_UINT_TO_PTR(fd) ) != NULL;
    356328}
    357329
     
    360332{
    361333    int s = -1;
    362 
    363334    tr_lockLock( gFd->lock );
    364335
     
    367338
    368339    if( priority || ( gFd->normal < gFd->normalMax ) )
    369        if( ( s = socket( AF_INET, type, 0 ) ) < 0 )
    370            tr_err( "Couldn't create socket (%s)", strerror( sockerrno ) );
     340        if( ( s = socket( AF_INET, type, 0 ) ) < 0 )
     341            tr_err( "Couldn't create socket (%s)", strerror( sockerrno ) );
    371342
    372343    if( s > -1 )
    373344    {
    374         SocketSetPriority( s, priority );
     345        setSocketPriority( s, priority );
     346
    375347        if( priority )
    376             gFd->reserved++;
     348            ++gFd->reserved;
    377349        else
    378             gFd->normal++;
    379     }
     350            ++gFd->normal;
     351    }
     352
     353    assert( gFd->reserved >= 0 );
     354    assert( gFd->normal >= 0 );
     355
    380356    tr_lockUnlock( gFd->lock );
    381 
    382357    return s;
    383358}
     
    387362{
    388363    int s = -1;
    389     unsigned len;
     364    unsigned int len;
    390365    struct sockaddr_in sock;
    391366
     
    401376    if( s > -1 )
    402377    {
    403         SocketSetPriority( s, 0 );
     378        setSocketPriority( s, 0 );
    404379        *addr = sock.sin_addr;
    405380        *port = sock.sin_port;
     
    424399tr_fdSocketClose( int s )
    425400{
    426     if( s >= 0 )
    427     {
    428         tr_lockLock( gFd->lock );
     401    tr_lockLock( gFd->lock );
     402
     403    if( s >= 0 ) {
    429404        socketClose( s );
    430         if( SocketGetPriority( s ) )
    431             gFd->reserved--;
     405        if( socketWasReserved( s ) )
     406            --gFd->reserved;
    432407        else
    433             gFd->normal--;
    434         tr_lockUnlock( gFd->lock );
    435     }
     408            --gFd->normal;
     409    }
     410
     411    assert( gFd->reserved >= 0 );
     412    assert( gFd->normal >= 0 );
     413
     414    tr_lockUnlock( gFd->lock );
    436415}
    437416
     
    465444
    466445    for( i=0; i<TR_MAX_OPEN_FILES; ++i )
    467         gFd->open[i].file = -1;
     446        gFd->open[i].fd = -1;
    468447         
    469448}
     
    481460    tr_condFree( gFd->cond );
    482461
    483     tr_free( gSockets );
     462    tr_list_free( &reservedSockets, NULL );
    484463    tr_free( gFd );
    485464}
Note: See TracChangeset for help on using the changeset viewer.