[Ace-users] [ace-users] TTY_IO: problem with asynchronous I/O

Steve Huston shuston at riverace.com
Tue Feb 5 17:08:48 CST 2008


Hi Robert,

Thanks for the PROBLEM-REPORT-FORM.

You'll most likely need to use a different set of I/O factory classes
for TTY I/O in the Proactor framework... Read/write stream are for
sockets. Try ACE_Asynch_Read_File, Write_File.

-Steve

--
Steve Huston, Riverace Corporation
Want to take ACE training on YOUR schedule?
See http://www.riverace.com/training.htm


> -----Original Message-----
> From: ace-users-bounces at cse.wustl.edu 
> [mailto:ace-users-bounces at cse.wustl.edu] On Behalf Of Robert
Lubaszka
> Sent: Tuesday, February 05, 2008 5:25 PM
> To: ace-users at cse.wustl.edu
> Subject: [ace-users] TTY_IO: problem with asynchronous I/O
> 
> 
>      ACE VERSION:
>          5.5.1
> 
>      HOST MACHINE and OPERATING SYSTEM:
>          Windows 2000 Pro SP4 / WINSOCK2
> 
>      TARGET MACHINE and OPERATING SYSTEM, if different from HOST:
> 
>      THE $ACE_ROOT/ace/config.h FILE:
>          config-win32.h
> 
>      THE $ACE_ROOT/include/makeinclude/platform_macros.GNU FILE: N/A
> 
>      CONTENTS OF 
> $ACE_ROOT/bin/MakeProjectCreator/config/default.features:  
> N/A
> 
>      AREA/CLASS/EXAMPLE AFFECTED:
> 
>      DOES THE PROBLEM AFFECT:
>          COMPILATION? No
>          LINKING? No
>          EXECUTION? Yes
>          OTHER (please specify)?
> 
>      SYNOPSIS:
> I'm trying to write serial port driver with asynchronous I/O. 
> I wrote  
> simple
> test code using ACE_Event_Handler ACE_DEV_Connector and 
> ACE_Reactor. After
> some "tricks" with overlapped I/O, specific 
> "register_handler" calling,
> specific "recv" etc, the test is running, but the reactor 
> loop does not  
> stop
> after specified timeout and handle_signal is called even when 
> no data  
> arrives.
> So I try to rewrite test code using Proactor pattern,
> but behaviour of the test is very similar.
> 
>      DESCRIPTION:
> I tried some "tricks" with port initialization ( like 
> OVERLAPPED flag ),  
> event
> handler registering, but it doesn't help. I'v got one of these:
> 
> "Reactor" version of test:
> 1. "Socket operation on non socket" after register_handler, or
> 2. "Invalid argument (22)" after register_handler, or
> 3. "Unknown error (997)" after send(...), or
> 4. no data reception ( probably improper port initialization ), or
> 5. infinite reactor loop..
> 
> "Proactor" version of test:
> 1. no input, no handle_read_stream(...) calls, or
> 2. "not connected (10057)" error after open(..) on 
> ACE_Asynch_Read_Stream,  
> or
> 3. infinite proactor loop..
> 
> What am I doing wrong?
> 
> 
>      REPEAT BY:
> Test code:
> 
> 
> =================================================
> "Reactor" version of test:
> =================================================
> #include <ace/OS.h>
> #include <ace/TTY_IO.h>
> #include <ace/Svc_Handler.h>
> #include <ace/DEV_Connector.h>
> #include <ace/Connector.h>
> #include <ace/Msg_WFMO_Reactor.h>
> #include <string>
> 
> #define RSBUFSZ 1024
> 
> class TestHandler: public ACE_Event_Handler
> {
> public:
>      ACE_DEV_Connector konektor_;
>      char rsbuf[RSBUFSZ];
>      OVERLAPPED ovr_;
> 
> public:
>      ACE_TTY_IO peer_;
>      TestHandler()
>      {
>          ACE_OS::memset( &ovr_, 0, sizeof( ovr_ ) );
>      };
>      virtual ~TestHandler() {};
> 
> //
> // If not overriden: "Invalid argument (22)" after 
> register_handler(..)
> //
>      virtual ACE_HANDLE get_handle( void ) const { return 
> ovr_.hEvent; }
> 
>      int open( const std::string& device, int baud )
>      {
>          int result = konektor_.connect( peer_,
>                                      ACE_DEV_Addr( device.c_str() ),
>                                      0, //timeout
>                                      ACE_Addr::sap_any,
>                                      0, //reuse
> //
> // if FILE_FLAG_OVERLAPPED enabled: "Unknown error (997)" 
> after send(..)
> //
> //                                    O_RDWR | FILE_FLAG_OVERLAPPED
);
>                                      O_RDWR );
>          if( result == 0 )
>          {
>              // set the appropriate parameters
>              ACE_TTY_IO::Serial_Params params;
>              result = peer_.control( ACE_TTY_IO::GETPARAMS, &params
);
>              params.baudrate = baud;
>              params.databits = 8;
>              params.stopbits = 1;
>              params.parityenb = 0;
>              params.ctsenb = 0;
>              params.rcvenb = 1;
>              params.rtsenb = 1;
>              params.dsrenb = 0;
>              result = peer_.control( ACE_TTY_IO::SETPARAMS, &params
);
>              if( result != 0 )
>              {
>                  ACE_DEBUG( ( LM_ERROR,
>                      ACE_TEXT( "TestDriver could not open 
> serial port  
> %s\n"),
>                      device.c_str() ) );
>                  return 0;
>              }
>          }
> 
>          ovr_.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
>          if ( peer_.recv( rsbuf, RSBUFSZ, &ovr_ ) == -1 )
>          {
>              ACE_ERROR( ( LM_ERROR,
>                          "Cannot initialize overlapped IO: %m 
> (%d).\n",
>                          ACE_OS::last_error() ) );
>          }
>          result = ACE_Reactor::instance()->register_handler( this );
>          if ( result != 0 )
>          {
>              ACE_ERROR( ( LM_ERROR,
>                      "%IFrameEventHandler: Cannot register 
> handler:%m  
> (%d).\n",
>                      ACE_OS::last_error() ) );
>          }
>          return result;
>      }
>      int handle_input( ACE_HANDLE fd = ACE_INVALID_HANDLE )
>      {
>          return handle_signal( 0, NULL, NULL );
>      }
> 
>      int handle_signal( int s, siginfo_t* sig, ucontext_t* con )
>      {
>          DWORD ncnt = peer_.recv( rsbuf, RSBUFSZ, &ovr_ );
>          if ( ncnt > 0 )
>          {
>              ACE_DEBUG( ( LM_INFO, ACE_TEXT( "dane: [%d]\n" 
), ncnt ) );
>          }
> #ifdef WIN32
>          else // this is a hack to avoid high resource 
> consumption on  
> windows !
>          {
>              ACE_OS::sleep( ACE_Time_Value( 0, 20000 ) );
>          }
> #endif
>          return 0;
>      }
> };
> 
> 
> int main( int argc, char* argv[] )
> {
>      TestHandler* driver = new TestHandler;
> 
>      if ( driver->open( "COM1", 9600 ) != 0 )
>      {
>          ACE_DEBUG( ( LM_ERROR,
>                       ACE_TEXT( "could not start TestHandler 
> !\n" ) ) );
>          return 0;
>      }
>      ACE_DEBUG( ( LM_INFO, ACE_TEXT( "started TestHandler !\n" ) )
);
> 
>      if ( driver->peer_.send( "fire 1\n", 7, &driver->ovr_ ) == -1 )
>      {
>          ACE_ERROR( ( LM_ERROR,
>                       "Cannot send ala ma kota: %m (%d).\n",
>                       ACE_OS::last_error() ) );
>          return -1;
>      }
>      ACE_DEBUG( ( LM_INFO, ACE_TEXT( "fire 1 !\n" ) ) );
>      ACE_OS::sleep( ACE_Time_Value( 2, 0 ) );
>      driver->peer_.send( "fire 2\n", 7 );
>      ACE_DEBUG( ( LM_INFO, ACE_TEXT( "fire 2 !\n" ) ) );
>      ACE_OS::sleep( ACE_Time_Value( 2, 0 ) );
>      driver->peer_.send( "fire 3\n", 7 );
>      ACE_DEBUG( ( LM_INFO, ACE_TEXT( "fire 3 !\n" ) ) );
>      ACE_Reactor::instance()->run_reactor_event_loop(
>                                  ACE_Time_Value( 20, 0 ) );
>      driver->peer_.close();
>      delete driver;
>      return 0;
> }
> 
> 
> =================================================
> "Proactor" version of test:
> =================================================
> #include <ace/Asynch_IO.h>
> #include <ace/OS.h>
> #include <ace/Message_Block.h>
> #include <ace/DEV_Connector.h>
> #include <ace/TTY_IO.h>
> #include <ace/Proactor.h>
> 
> class TTYService: public ACE_Handler
> {
> private:
>      ACE_Asynch_Read_Stream reader_;
>      ACE_Asynch_Write_Stream writer_;
> 
> public:
>      ~TTYService()
>      {
>      }
> 
>      void openTTY()
>      {
>          ACE_TTY_IO peer_;
>          ACE_DEV_Connector connector_;
> 
>          int result = connector_.connect( peer_,
>                                          ACE_DEV_Addr( "COM1" ),
>                                          0, //timeout
>                                          ACE_Addr::sap_any,
>                                          0, //reuse
>                                          O_RDWR | 
> FILE_FLAG_OVERLAPPED );
> //
> // If FILE_FLAG_OVERLAPPED not set: no data input,
> // no handle_read_stream(...) calling
> //
>          if( result == 0 )
>          {
>              // set the appropriate parameters
>              ACE_TTY_IO::Serial_Params params;
>              result = peer_.control( ACE_TTY_IO::GETPARAMS, &params
);
>              params.baudrate = 9600;
>              params.databits = 8;
>              params.stopbits = 1;
>              params.parityenb = 0;
>              params.ctsenb = 0;
>              params.rcvenb = 1;
>              params.rtsenb = 1;
>              params.dsrenb = 0;
>              result = peer_.control( ACE_TTY_IO::SETPARAMS, &params
);
>              if( result != 0 )
>              {
>                  //error;
>                  return;
>              }
>          }
> 
> //
> // If second argument ( "peer_.get_handle()" ) not set:
> // "not connected (10057)" error
> //        if ( this->reader_.open( *this ) != 0 )
>          if ( this->reader_.open( *this, peer_.get_handle() ) != 0 )
>          {
>              ACE_ERROR( ( LM_ERROR,
>                           "BLAD: %m (%d).\n", 
> ACE_OS::last_error() ) );
>              return;
>          }
> //
> // If second argument ( "peer_.get_handle()" ) not set:
> // "not connected (10057)" error
> //        if ( this->writer_.open( *this ) != 0 )
>          if ( this->writer_.open( *this, peer_.get_handle() ) != 0 )
>          {
>              ACE_ERROR( ( LM_ERROR,
>                           "BLAD: %m (%d).\n", 
> ACE_OS::last_error() ) );
>              return;
>          }
>          ACE_Message_Block* mb;
>          ACE_NEW_NORETURN( mb, ACE_Message_Block( 1024 ) );
>          if ( this->reader_.read( *mb, mb->space() ) != 0 )
>          {
>              //ERROR!!!
>              mb->release();
>              return;
>          }
>          return;
>      }
> 
>      virtual void handle_read_stream(
>                          const 
> ACE_Asynch_Read_Stream::Result& result )
>      {
>          ACE_Message_Block& mb = result.message_block();
>          bool sukces = result.success();
>          int trsf = result.bytes_transferred();
>          if ( !sukces )
>          {
>              mb.release();
>              delete this;
>              return;
>          }
>          if ( trsf != 0 )
>          {
>              if ( this->writer_.write( mb, mb.length() ) != 0 )
>              {
>                  //ERROR
>                  mb.release();
>                  return;
>              }
>          }
>          else
>          {
>              mb.release();
> #ifdef WIN32
>              // this is a hack to avoid high resource consumption on

> windows !
>              ACE_OS::sleep( ACE_Time_Value( 0, 20000 ) );
> #endif
>          }
>          ACE_Message_Block* new_mb;
>          ACE_NEW_NORETURN( new_mb, ACE_Message_Block( 1024 ) );
>          this->reader_.read( *new_mb, new_mb->space() );
>          return;
>      }
> 
>      virtual void handle_write_stream(
>                          const 
> ACE_Asynch_Write_Stream::Result& result )
>      {
>          result.message_block().release();
>          return;
>      }
> };
> 
> int main( int argc, ACE_TCHAR *argv[] )
> {
>      TTYService service;
>      service.openTTY();
> 
>      int success = ACE_Proactor::instance()->run_event_loop(
>                                                  
> ACE_Time_Value( 20, 0 ) );
>      return 0;
> }
> 
> -- 
> Używam klienta poczty Opera
> 
> _______________________________________________
> ace-users mailing list
> ace-users at mail.cse.wustl.edu
> http://mail.cse.wustl.edu/mailman/listinfo/ace-users
> 




More information about the Ace-users mailing list