diff options
author | Mike Buland <eichlan@xagasoft.com> | 2023-08-01 11:38:26 -0700 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2023-08-01 11:38:26 -0700 |
commit | 87d76df1720e29e4195cf4a8845c07450fb3b2f2 (patch) | |
tree | 6a62b8e4326570ccdbe01bfb8c71f408f6c01e2d | |
parent | dcf2e2182934291e7312993c78d3d3c5f72597d5 (diff) | |
download | libbu++-87d76df1720e29e4195cf4a8845c07450fb3b2f2.tar.gz libbu++-87d76df1720e29e4195cf4a8845c07450fb3b2f2.tar.bz2 libbu++-87d76df1720e29e4195cf4a8845c07450fb3b2f2.tar.xz libbu++-87d76df1720e29e4195cf4a8845c07450fb3b2f2.zip |
Fixed issues around disconnected sockets.
We were bailing out when sockets closed, that was silly.
-rw-r--r-- | src/stable/server.cpp | 97 | ||||
-rw-r--r-- | src/stable/server.h | 2 | ||||
-rw-r--r-- | src/stable/sockettcp.h | 7 |
3 files changed, 75 insertions, 31 deletions
diff --git a/src/stable/server.cpp b/src/stable/server.cpp index 3aa8a34..6ee7d6e 100644 --- a/src/stable/server.cpp +++ b/src/stable/server.cpp | |||
@@ -247,6 +247,8 @@ void Bu::Server::addClient( const Bu::ServerSocket *pSrv, Bu::Socket *pSocket ) | |||
247 | Bu::Client *Bu::Server::getClient( fd iId ) | 247 | Bu::Client *Bu::Server::getClient( fd iId ) |
248 | { | 248 | { |
249 | Bu::MutexLocker l( mClients ); | 249 | Bu::MutexLocker l( mClients ); |
250 | if( !hClients.has( iId ) ) | ||
251 | return NULL; | ||
250 | return hClients.get( iId ); | 252 | return hClients.get( iId ); |
251 | } | 253 | } |
252 | 254 | ||
@@ -520,30 +522,38 @@ void Bu::Server::IoWorker::handleRead( Client *pClient, Socket *pSocket ) | |||
520 | Bu::size iTotal=0; | 522 | Bu::size iTotal=0; |
521 | 523 | ||
522 | BU_PROFILE_START("client.read"); | 524 | BU_PROFILE_START("client.read"); |
523 | for(;;) | 525 | try |
524 | { | 526 | { |
525 | try | 527 | for(;;) |
526 | { | 528 | { |
527 | iRead = pSocket->read( buf, RBS ); | 529 | try |
528 | |||
529 | if( iRead == 0 ) | ||
530 | { | 530 | { |
531 | break; | 531 | iRead = pSocket->read( buf, RBS ); |
532 | |||
533 | if( iRead == 0 ) | ||
534 | { | ||
535 | break; | ||
536 | } | ||
537 | else | ||
538 | { | ||
539 | iTotal += iRead; | ||
540 | pClient->cbBuffer.server().write( buf, iRead ); | ||
541 | if( !pSocket->canRead() ) | ||
542 | break; | ||
543 | } | ||
532 | } | 544 | } |
533 | else | 545 | catch( Bu::ExceptionBase &e ) |
534 | { | 546 | { |
535 | iTotal += iRead; | 547 | pClient->disconnect(); |
536 | pClient->cbBuffer.server().write( buf, iRead ); | 548 | //close( pSocket ); |
537 | if( !pSocket->canRead() ) | 549 | return; |
538 | break; | ||
539 | } | 550 | } |
540 | } | 551 | } |
541 | catch( Bu::ExceptionBase &e ) | 552 | } |
542 | { | 553 | catch( std::exception &e ) |
543 | pClient->disconnect(); | 554 | { |
544 | //close( pSocket ); | 555 | // Probably the socket is dead. We should maybe disconnect, but we'll |
545 | return; | 556 | // also notice soon enough anyway? |
546 | } | ||
547 | } | 557 | } |
548 | BU_PROFILE_END("client.read"); | 558 | BU_PROFILE_END("client.read"); |
549 | 559 | ||
@@ -565,12 +575,28 @@ void Bu::Server::IoWorker::handleRead( Client *pClient, Socket *pSocket ) | |||
565 | void Bu::Server::IoWorker::handleWrite( Client *pClient, Socket *pSocket ) | 575 | void Bu::Server::IoWorker::handleWrite( Client *pClient, Socket *pSocket ) |
566 | { | 576 | { |
567 | char buf[RBS]; | 577 | char buf[RBS]; |
568 | while( pClient->hasOutput() > 0 ) | 578 | try |
579 | { | ||
580 | while( pClient->hasOutput() ) | ||
581 | { | ||
582 | int iAmnt = RBS; | ||
583 | iAmnt = pClient->cbBuffer.server().peek( buf, iAmnt ); | ||
584 | int iReal = pSocket->write( buf, iAmnt ); | ||
585 | pClient->cbBuffer.server().seek( iReal ); | ||
586 | if( iReal < iAmnt ) | ||
587 | { | ||
588 | // We wrote less than expected, the kernel buffer must be full, | ||
589 | // we should queue ourselves again. | ||
590 | rSrv.clientWriteReady( pClient->getId() ); | ||
591 | break; | ||
592 | } | ||
593 | } | ||
594 | } | ||
595 | catch( std::exception &e ) | ||
569 | { | 596 | { |
570 | int iAmnt = RBS; | 597 | // Error working with socket, it's probably closed. |
571 | iAmnt = pClient->cbBuffer.server().peek( buf, iAmnt ); | 598 | if( pClient->hasOutput() ) |
572 | int iReal = pSocket->write( buf, iAmnt ); | 599 | rSrv.clientWriteReady( pClient->getId() ); |
573 | pClient->cbBuffer.server().seek( iReal ); | ||
574 | } | 600 | } |
575 | } | 601 | } |
576 | 602 | ||
@@ -596,17 +622,28 @@ void Bu::Server::ClientWorker::run() | |||
596 | if( pEv == NULL ) | 622 | if( pEv == NULL ) |
597 | continue; | 623 | continue; |
598 | 624 | ||
599 | Client *pClient = rSrv.getClient( pEv->getId() ); | 625 | try |
600 | if( pClient == NULL ) | ||
601 | { | 626 | { |
602 | delete pEv; | 627 | Client *pClient = rSrv.getClient( pEv->getId() ); |
603 | continue; | 628 | if( pClient == NULL ) |
629 | { | ||
630 | delete pEv; | ||
631 | continue; | ||
632 | } | ||
633 | |||
634 | pClient->processInput(); | ||
635 | if( pClient->getOutputSize() > 0 ) | ||
636 | { | ||
637 | rSrv.clientWriteReady( pClient->getId() ); | ||
638 | } | ||
604 | } | 639 | } |
605 | 640 | catch( std::exception &e ) | |
606 | pClient->processInput(); | 641 | { |
607 | if( pClient->getOutputSize() > 0 ) | 642 | // Probably we're fine, the client just closed between queuing and |
643 | // working. | ||
644 | } | ||
645 | catch(...) | ||
608 | { | 646 | { |
609 | rSrv.clientWriteReady( pClient->getId() ); | ||
610 | } | 647 | } |
611 | delete pEv; | 648 | delete pEv; |
612 | } | 649 | } |
diff --git a/src/stable/server.h b/src/stable/server.h index 9fb8282..a9680cf 100644 --- a/src/stable/server.h +++ b/src/stable/server.h | |||
@@ -23,7 +23,7 @@ | |||
23 | #include "bu/config.h" | 23 | #include "bu/config.h" |
24 | 24 | ||
25 | #ifndef PROFILE_BU_SERVER | 25 | #ifndef PROFILE_BU_SERVER |
26 | #define PROFILE_BU_SERVER 1 | 26 | // #define PROFILE_BU_SERVER 1 |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | #ifdef PROFILE_BU_SERVER | 29 | #ifdef PROFILE_BU_SERVER |
diff --git a/src/stable/sockettcp.h b/src/stable/sockettcp.h index 3fc14ef..8539b52 100644 --- a/src/stable/sockettcp.h +++ b/src/stable/sockettcp.h | |||
@@ -48,7 +48,14 @@ namespace Bu | |||
48 | ... | 48 | ... |
49 | ... | 49 | ... |
50 | ... | 50 | ... |
51 | // sigset is deprecated | ||
51 | sigset( SIGPIPE, SIG_IGN ); // do this before you use a Bu::SocketTcp | 52 | sigset( SIGPIPE, SIG_IGN ); // do this before you use a Bu::SocketTcp |
53 | |||
54 | // this is the modern Linux alternative | ||
55 | struct sigaction saIgnore; | ||
56 | memset( &saIgnore, 0, sizeof(struct sigaction) ); | ||
57 | saIgnore.sa_handler = SIG_IGN; | ||
58 | sigaction( SIGPIPE, &saIgnore, NULL ); | ||
52 | @endcode | 59 | @endcode |
53 | * When this is done, Bu::SocketTcp will simply throw a broken pipe | 60 | * When this is done, Bu::SocketTcp will simply throw a broken pipe |
54 | * exception just like every other error condition, allowing your program | 61 | * exception just like every other error condition, allowing your program |