mirror of
https://github.com/transmission/transmission
synced 2024-12-25 17:17:31 +00:00
(trunk libT) #2842 "Transmission crashes randomly on ARM-based Synology NAS" -- experimental commit based on giovannibajo's suggestion in comment:39 about the list struct's alignment
This commit is contained in:
parent
358bce52fd
commit
4f5670f9c0
4 changed files with 14 additions and 114 deletions
|
@ -157,50 +157,3 @@ tr_list_size( const tr_list * list )
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Double-linked list with easy memory management and fast
|
||||
* insert/remove operations
|
||||
*/
|
||||
|
||||
|
||||
void
|
||||
__tr_list_insert( struct __tr_list * list,
|
||||
struct __tr_list * prev,
|
||||
struct __tr_list * next)
|
||||
{
|
||||
next->prev = list;
|
||||
list->next = next;
|
||||
list->prev = prev;
|
||||
prev->next = list;
|
||||
}
|
||||
|
||||
static void
|
||||
__tr_list_splice( struct __tr_list * prev,
|
||||
struct __tr_list * next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
void
|
||||
__tr_list_remove( struct __tr_list * head )
|
||||
{
|
||||
__tr_list_splice( head->prev, head->next );
|
||||
head->next = head->prev = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
__tr_list_destroy( struct __tr_list * head,
|
||||
__tr_list_free_t func)
|
||||
{
|
||||
while ( head->next != head )
|
||||
{
|
||||
struct __tr_list * list = head->next;
|
||||
__tr_list_splice( list->prev, list->next );
|
||||
|
||||
func( list );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,51 +101,6 @@ tr_list* tr_list_find( tr_list * list,
|
|||
TrListCompareFunc compare_func );
|
||||
|
||||
|
||||
/** @brief Double-linked list with easy memory management and fast insert/remove operations */
|
||||
struct __tr_list
|
||||
{
|
||||
struct __tr_list * next, * prev;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Given a __tr_list node that's embedded in a struct, returns a pointer to the struct.
|
||||
* @param ptr pointer to the embedded __tr_list
|
||||
* @param type struct type that has contains the __tr_list
|
||||
* @param field the name of the struct's _tr_list field
|
||||
*/
|
||||
#define __tr_list_entry(ptr,type,field) ((type*) (((char*)ptr) - offsetof(type,field)))
|
||||
|
||||
typedef int ( *__tr_list_cmp_t ) ( const void * a, const void * b );
|
||||
typedef void ( *__tr_list_free_t )( void * );
|
||||
|
||||
|
||||
/** @brief Init @head as an empty list. */
|
||||
static inline void
|
||||
__tr_list_init( struct __tr_list * head )
|
||||
{
|
||||
head->next = head->prev = head;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Insert @list between @prev and @next. */
|
||||
void
|
||||
__tr_list_insert( struct __tr_list * list,
|
||||
struct __tr_list * prev,
|
||||
struct __tr_list * next);
|
||||
|
||||
/** @brief Append @list to the end of @head. */
|
||||
static inline void
|
||||
__tr_list_append( struct __tr_list * head, struct __tr_list * list)
|
||||
{
|
||||
__tr_list_insert( list, head->prev, head );
|
||||
}
|
||||
|
||||
/** @brief Remove @head from the list it is in. */
|
||||
void __tr_list_remove( struct __tr_list * head );
|
||||
|
||||
/** @brief Destroy the list and free all nodes */
|
||||
void __tr_list_destroy( struct __tr_list * head, __tr_list_free_t func );
|
||||
|
||||
/* @} */
|
||||
#endif /* TR_LIST_H */
|
||||
|
||||
|
|
|
@ -75,7 +75,6 @@ struct tr_datatype
|
|||
{
|
||||
tr_bool isPieceData;
|
||||
size_t length;
|
||||
struct __tr_list head;
|
||||
};
|
||||
|
||||
/***
|
||||
|
@ -87,7 +86,8 @@ didWriteWrapper( tr_peerIo * io, size_t bytes_transferred )
|
|||
{
|
||||
while( bytes_transferred && tr_isPeerIo( io ) )
|
||||
{
|
||||
struct tr_datatype * next = __tr_list_entry( io->outbuf_datatypes.next, struct tr_datatype, head );
|
||||
struct tr_datatype * next = io->outbuf_datatypes->data;
|
||||
|
||||
const size_t payload = MIN( next->length, bytes_transferred );
|
||||
const size_t overhead = guessPacketOverhead( payload );
|
||||
|
||||
|
@ -104,7 +104,7 @@ didWriteWrapper( tr_peerIo * io, size_t bytes_transferred )
|
|||
bytes_transferred -= payload;
|
||||
next->length -= payload;
|
||||
if( !next->length ) {
|
||||
__tr_list_remove( io->outbuf_datatypes.next );
|
||||
tr_list_pop_front( &io->outbuf_datatypes );
|
||||
tr_free( next );
|
||||
}
|
||||
}
|
||||
|
@ -413,8 +413,6 @@ tr_peerIoNew( tr_session * session,
|
|||
event_set( &io->event_read, io->socket, EV_READ, event_read_cb, io );
|
||||
event_set( &io->event_write, io->socket, EV_WRITE, event_write_cb, io );
|
||||
|
||||
__tr_list_init( &io->outbuf_datatypes );
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
|
@ -463,6 +461,7 @@ event_enable( tr_peerIo * io, short event )
|
|||
assert( tr_amInEventThread( io->session ) );
|
||||
assert( io->session != NULL );
|
||||
assert( io->session->events != NULL );
|
||||
assert( io->socket >= 0 );
|
||||
assert( event_initialized( &io->event_read ) );
|
||||
assert( event_initialized( &io->event_write ) );
|
||||
|
||||
|
@ -527,13 +526,6 @@ tr_peerIoSetEnabled( tr_peerIo * io,
|
|||
****
|
||||
***/
|
||||
|
||||
static void
|
||||
trDatatypeFree( void * data )
|
||||
{
|
||||
struct tr_datatype * dt = __tr_list_entry( data, struct tr_datatype, head );
|
||||
tr_free(dt);
|
||||
}
|
||||
|
||||
static void
|
||||
io_dtor( void * vio )
|
||||
{
|
||||
|
@ -550,7 +542,7 @@ io_dtor( void * vio )
|
|||
evbuffer_free( io->inbuf );
|
||||
tr_netClose( io->session, io->socket );
|
||||
tr_cryptoFree( io->crypto );
|
||||
__tr_list_destroy( &io->outbuf_datatypes, trDatatypeFree );
|
||||
tr_list_free( &io->outbuf_datatypes, tr_free );
|
||||
|
||||
memset( io, ~0, sizeof( tr_peerIo ) );
|
||||
tr_free( io );
|
||||
|
@ -816,9 +808,7 @@ tr_peerIoWrite( tr_peerIo * io,
|
|||
datatype = tr_new( struct tr_datatype, 1 );
|
||||
datatype->isPieceData = isPieceData != 0;
|
||||
datatype->length = byteCount;
|
||||
|
||||
__tr_list_init( &datatype->head );
|
||||
__tr_list_append( &io->outbuf_datatypes, &datatype->head );
|
||||
tr_list_append( &io->outbuf_datatypes, datatype );
|
||||
|
||||
switch( io->encryptionMode )
|
||||
{
|
||||
|
@ -997,15 +987,17 @@ int
|
|||
tr_peerIoFlushOutgoingProtocolMsgs( tr_peerIo * io )
|
||||
{
|
||||
size_t byteCount = 0;
|
||||
struct __tr_list * walk;
|
||||
struct __tr_list * fencepost = &io->outbuf_datatypes;
|
||||
tr_list * it;
|
||||
|
||||
/* count up how many bytes are used by non-piece-data messages
|
||||
at the front of our outbound queue */
|
||||
for( walk=fencepost->next; walk!=fencepost; walk=walk->next ) {
|
||||
struct tr_datatype * d = __tr_list_entry( walk, struct tr_datatype, head );
|
||||
for( it=io->outbuf_datatypes; it!=NULL; it=it->next )
|
||||
{
|
||||
struct tr_datatype * d = it->data;
|
||||
|
||||
if( d->isPieceData )
|
||||
break;
|
||||
|
||||
byteCount += d->length;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include "transmission.h"
|
||||
#include "bandwidth.h"
|
||||
#include "list.h" /* __tr_list */
|
||||
#include "list.h" /* tr_list */
|
||||
#include "net.h" /* tr_address */
|
||||
|
||||
struct evbuffer;
|
||||
|
@ -106,7 +106,7 @@ typedef struct tr_peerIo
|
|||
|
||||
struct evbuffer * inbuf;
|
||||
struct evbuffer * outbuf;
|
||||
struct __tr_list outbuf_datatypes; /* struct tr_datatype */
|
||||
struct tr_list * outbuf_datatypes; /* struct tr_datatype */
|
||||
|
||||
struct event event_read;
|
||||
struct event event_write;
|
||||
|
|
Loading…
Reference in a new issue