aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitlbee.c26
-rw-r--r--irc.c18
-rw-r--r--irc.h4
3 files changed, 32 insertions, 16 deletions
diff --git a/bitlbee.c b/bitlbee.c
index f4eba866..d8bf12d7 100644
--- a/bitlbee.c
+++ b/bitlbee.c
@@ -199,7 +199,7 @@ gboolean bitlbee_io_current_client_read( GIOChannel *source, GIOCondition condit
if( !irc_process( irc ) )
{
log_message( LOGLVL_INFO, "Destroying connection with fd %d.", irc->fd );
- irc_free( irc );
+ irc_abort( irc );
return FALSE;
}
@@ -207,7 +207,7 @@ gboolean bitlbee_io_current_client_read( GIOChannel *source, GIOCondition condit
if( irc->readbuffer && ( strlen( irc->readbuffer ) > 1024 ) )
{
log_message( LOGLVL_ERROR, "Maximum line length exceeded." );
- irc_free( irc );
+ irc_abort( irc );
return FALSE;
}
@@ -226,25 +226,25 @@ gboolean bitlbee_io_current_client_write( GIOChannel *source, GIOCondition condi
size = strlen( irc->sendbuffer );
st = write( irc->fd, irc->sendbuffer, size );
- if( st <= 0 )
+ if( st == 0 || ( st < 0 && !sockerr_again() ) )
{
- if( sockerr_again() )
- {
- return TRUE;
- }
- else
- {
- irc_free( irc );
- return FALSE;
- }
+ irc_free( irc );
+ return FALSE;
+ }
+ else if( st < 0 ) /* && sockerr_again() */
+ {
+ return TRUE;
}
if( st == size )
{
g_free( irc->sendbuffer );
irc->sendbuffer = NULL;
-
irc->w_watch_source_id = 0;
+
+ if( irc->status == USTATUS_SHUTDOWN )
+ irc_free( irc );
+
return( FALSE );
}
else
diff --git a/irc.c b/irc.c
index 32dadb7c..9db4becb 100644
--- a/irc.c
+++ b/irc.c
@@ -150,6 +150,20 @@ irc_t *irc_new( int fd )
return( irc );
}
+void irc_abort( irc_t *irc )
+{
+ irc->status = USTATUS_SHUTDOWN;
+ if( irc->sendbuffer )
+ {
+ g_source_remove( irc->r_watch_source_id );
+ irc->r_watch_source_id = g_timeout_add_full( G_PRIORITY_HIGH, 1000, (GSourceFunc) irc_free, irc, NULL );
+ }
+ else
+ {
+ irc_free( irc );
+ }
+}
+
static gboolean irc_free_userhash( gpointer key, gpointer value, gpointer data )
{
g_free( key );
@@ -158,7 +172,7 @@ static gboolean irc_free_userhash( gpointer key, gpointer value, gpointer data )
}
/* Because we have no garbage collection, this is quite annoying */
-void irc_free(irc_t * irc)
+void irc_free( irc_t * irc )
{
account_t *account, *accounttmp;
user_t *user, *usertmp;
@@ -495,7 +509,7 @@ int irc_exec( irc_t *irc, char **cmd )
else if( g_strcasecmp( cmd[0], "QUIT" ) == 0 )
{
irc_write( irc, "ERROR :%s%s", cmd[1]?"Quit: ":"", cmd[1]?cmd[1]:"Client Quit" );
- g_io_channel_close( irc->io_channel );
+ /* g_io_channel_close( irc->io_channel ); */
return( 0 );
}
diff --git a/irc.h b/irc.h
index 32b19642..46391cb7 100644
--- a/irc.h
+++ b/irc.h
@@ -43,7 +43,8 @@ typedef enum
USTATUS_OFFLINE,
USTATUS_AUTHORIZED,
USTATUS_LOGGED_IN,
- USTATUS_IDENTIFIED
+ USTATUS_IDENTIFIED,
+ USTATUS_SHUTDOWN
} irc_status_t;
typedef struct channel
@@ -103,6 +104,7 @@ typedef struct irc
extern GSList *irc_connection_list;
irc_t *irc_new( int fd );
+void irc_abort( irc_t *irc );
void irc_free( irc_t *irc );
int irc_exec( irc_t *irc, char **cmd );