[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, ¶ms
);
> 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, ¶ms
);
> 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, ¶ms
);
> 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, ¶ms
);
> 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