From 9e78b768245db7136ebbed5e6e1e955d8218632d Mon Sep 17 00:00:00 2001 From: Joachim Achtzehnter Date: Wed, 19 Aug 2020 14:55:54 -0700 Subject: [PATCH 1/7] Repro problem with fragmented GIOP messages --- .../Big_String_Sequence/Echo.idl | 18 +++++ .../Big_String_Sequence/Echo_Client_i.cpp | 78 +++++++++++++++++++ .../Big_String_Sequence/Echo_Client_i.h | 34 ++++++++ .../Big_String_Sequence/Echo_i.cpp | 62 +++++++++++++++ .../Big_String_Sequence/Echo_i.h | 54 +++++++++++++ .../Big_String_Sequence/README.md | 19 +++++ .../Big_String_Sequence/client.cpp | 19 +++++ .../Big_String_Sequence/echo.mpc | 34 ++++++++ .../Big_String_Sequence/run_test.pl | 75 ++++++++++++++++++ .../Big_String_Sequence/server.cpp | 42 ++++++++++ 10 files changed, 435 insertions(+) create mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl create mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp create mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.h create mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp create mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h create mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md create mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp create mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc create mode 100755 TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl create mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl new file mode 100644 index 0000000000000..28db1a83dade4 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl @@ -0,0 +1,18 @@ +/* -*- C++ -*- */ +#if !defined (_ECHO_IDL) +#define _ECHO_IDL + +interface Echo +{ + // = TITLE + // Defines an interface that encapsulates an operation that returns + // a string sequence. + + typedef sequence List; + + List return_list (); + + oneway void shutdown (); +}; + +#endif /* _ECHO_IDL */ diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp new file mode 100644 index 0000000000000..d779208205dd4 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp @@ -0,0 +1,78 @@ +#include "Echo_Client_i.h" +#include "ace/Get_Opt.h" +#include "ace/Read_Buffer.h" +#include "ace/OS_NS_unistd.h" +#include +#include + +// This is the interface program that accesses the remote object + +// Constructor. +Echo_Client_i::Echo_Client_i (void) +{ + //no-op +} + +//Destructor. +Echo_Client_i::~Echo_Client_i (void) +{ + //no-op +} + +int +Echo_Client_i::run (const char *name, + int argc, + ACE_TCHAR *argv[]) +{ + // Initialize the client. + if (client_.init (name, argc, argv) == -1) + return -1; + + try + { + Echo::List_var list = client_->return_list(); + std::cout << "Received list of length " + << list->length() << std::endl; + if (list->length() != 2) + { + std::cout << "ERROR: Expected length 2, exiting..." << std::endl; + client_->shutdown (); + return -1; + } + const char* value = (*list)[0].in(); + size_t length = std::strlen(value); + std::cout << "First element has length " + << length << std::endl; + for (size_t n = 0; n < length; ++n) + { + if (value[n] != 'A') + { + std::cout << "ERROR: Character at position " << n + << " should be 'A', but is '" + << value[n] << "'" << std::endl; + client_->shutdown (); + return -1; + } + } + value = (*list)[1].in(); + length = std::strlen(value); + std::cout << "Second element has length " + << length << std::endl; + std::cout << "Value: " << value << std::endl; + if (std::strcmp(value, "Hello World") != 0) + { + std::cout << "ERROR: Expected \"Hello World\", exiting..." + << std::endl; + client_->shutdown (); + return -1; + } + client_->shutdown (); + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("\n Exception in RMI"); + return -1; + } + + return 0; +} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.h b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.h new file mode 100644 index 0000000000000..82d35d53f187e --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.h @@ -0,0 +1,34 @@ +// -*- C++ -*- + +#ifndef ECHO_CLIENT_I_H +#define ECHO_CLIENT_I_H + +#include "../../../examples/Simple/Simple_util.h" +#include "EchoC.h" + +/** + * @class Echo_Client_i + * + * @brief Echo_Client interface subclass. + * + * This class implements the interface between the interface + * objects and the client . + */ +class Echo_Client_i +{ +public: + /// Constructor + Echo_Client_i (void); + + /// Destructor + ~Echo_Client_i (void); + + /// Execute the methods + int run (const char *, int, ACE_TCHAR **); + +private: + /// Instantiate the client object. + Client client_; +}; + +#endif /* TIME_CLIENT_I_H */ diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp new file mode 100644 index 0000000000000..058861f762461 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp @@ -0,0 +1,62 @@ +#include +#include "Echo_i.h" + +// Constructor. + +Echo_i::Echo_i (void) +{ +} + +// Destructor. + +Echo_i::~Echo_i (void) +{ +} + +// Set the ORB pointer. + +void +Echo_i::orb (CORBA::ORB_ptr o) +{ + this->orb_ = CORBA::ORB::_duplicate (o); +} + +// Return a list of strings. + +Echo::List * +Echo_i::return_list () +{ + Echo::List_var list; + + { + Echo::List *tmp = 0; + ACE_NEW_RETURN (tmp, + Echo::List (2), + 0); + // Pass ownership to the _var, pitty that ACE_NEW_RETURN cannot + // assign to T_vars directly. + list = tmp; + } + + list->length (2); + + // Just do something to get a 'big' list of strings. + std::string big(4 * 1024 * 1024, 'A'); + std::string small("Hello World"); + list[CORBA::ULong(0)] = CORBA::string_dup(big.c_str()); + list[CORBA::ULong(1)] = CORBA::string_dup(small.c_str()); + + return list._retn (); +} + +// Shutdown the server application. + +void +Echo_i::shutdown (void) +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\nThe echo server is shutting down\n"))); + + // Instruct the ORB to shutdown. + this->orb_->shutdown (); +} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h new file mode 100644 index 0000000000000..7e0822ebe264e --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h @@ -0,0 +1,54 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Echo_i.h + * + * This class implements the Echo IDL interface. + * + * @author Kirthika Parameswaran + */ +//============================================================================= + + +#ifndef ECHO_I_H +#define ECHO_I_H + +#include "EchoS.h" + +/** + * @class Echo_i + * + * @brief Echo Object Implementation + * + * The object implementation performs the following functions: + * -- To return the string which needs to be displayed + * from the server. + * -- shuts down the server + */ +class Echo_i : public POA_Echo +{ +public: + /// Constructor. + Echo_i (void); + + /// Destructor. + virtual ~Echo_i (void); + + /// Return the mesg string back from the server. + virtual Echo::List *return_list (); + + /// Shutdown the server. + virtual void shutdown (); + + /// Set the ORB pointer. + void orb (CORBA::ORB_ptr o); + +private: + /// ORB pointer. + CORBA::ORB_var orb_; + + void operator= (const Echo_i&); +}; + +#endif /* ECHO_I_H */ diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md b/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md new file mode 100644 index 0000000000000..235eb9fb32ae4 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md @@ -0,0 +1,19 @@ +# TAO GIOP Fragmentation Bug +## Reproduces a bug when GIOP fragmentation is used + +The server returns a string sequence with two elements, the first is a +long 4MB string with repeating character 'A', the second element is +the string "Hello World". If one removes the command line parameters +`-ORBMaxMessageSize 1048576` from `run_test.pl` everything +works as expected, but with these settings, which cause GIOP +fragmentation, the client receives an empty string as the second +element of the sequence. + +We discovered problems in a more complicated application when big +sequences are returned, often the client encountering +`CORBA::MARSHAL` or `CORBA::COMM_FAILURE` exceptions. In one +case, it worked if the sequence contained a single element, even if +big, but a small second element caused client exceptions. The complex +application encountered problems with big sequences even without the +`-ORBMaxMessageSize` parameter, but problems start at smaller +sizes if it is used. \ No newline at end of file diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp new file mode 100644 index 0000000000000..d3851527028c0 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp @@ -0,0 +1,19 @@ +# include "Echo_Client_i.h" + +// The client program for the application. + +int +ACE_TMAIN(int argc, ACE_TCHAR *argv[]) +{ + Echo_Client_i client; + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\nEcho client\n\n"))); + + if (client.run ("Echo", + argc, + argv) == -1) + return -1; + else + return 0; +} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc b/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc new file mode 100644 index 0000000000000..ddd71d2634186 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc @@ -0,0 +1,34 @@ +// -*- MPC -*- +project(*idl): taoidldefaults { + IDL_Files { + Echo.idl + } + custom_only = 1 +} + +project(*Server): taoserver, namingexe, iortable, utils, avoids_corba_e_micro { + exename = server + after += *idl + Source_Files { + Echo_i.cpp + ../../../examples/Simple/Simple_util.cpp + server.cpp + EchoS.cpp + EchoC.cpp + } + IDL_Files { + } +} + +project(*Client): taoclient, namingexe, iortable, utils { + exename = client + after += *IDL + Source_Files { + Echo_Client_i.cpp + ../../../examples/Simple/Simple_util.cpp + client.cpp + EchoC.cpp + } + IDL_Files { + } +} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl b/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl new file mode 100755 index 0000000000000..6d6d869d2a46c --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl @@ -0,0 +1,75 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# -*- perl -*- + +use lib "$ENV{ACE_ROOT}/bin"; +use PerlACE::TestTarget; + +$status = 0; +$debug_level = '0'; + +foreach $i (@ARGV) { + if ($i eq '-debug') { + $debug_level = '10'; + } +} + +my $server = PerlACE::TestTarget::create_target (1) || die "Create target 1 failed\n"; +my $client = PerlACE::TestTarget::create_target (2) || die "Create target 2 failed\n"; + +my $iorbase = "server.ior"; +my $server_iorfile = $server->LocalFile ($iorbase); +my $client_iorfile = $client->LocalFile ($iorbase); +$server->DeleteFile($iorbase); +$client->DeleteFile($iorbase); + +$SV = $server->CreateProcess ("server", "-ORBMaxMessageSize 1048576 -ORBdebuglevel $debug_level -ORBLogFile server_log.txt -o $server_iorfile"); +$CL = $client->CreateProcess ("client", "-ORBdebuglevel $debug_level -ORBLogFile client_log.txt -f $client_iorfile -x"); +$server_status = $SV->Spawn (); + +if ($server_status != 0) { + print STDERR "ERROR: server returned $server_status\n"; + exit 1; +} + +if ($server->WaitForFileTimed ($iorbase, + $server->ProcessStartWaitInterval()) == -1) { + print STDERR "ERROR: cannot find file <$server_iorfile>\n"; + $SV->Kill (); $SV->TimedWait (1); + exit 1; +} + +if ($server->GetFile ($iorbase) == -1) { + print STDERR "ERROR: cannot retrieve file <$server_iorfile>\n"; + $SV->Kill (); $SV->TimedWait (1); + exit 1; +} +if ($client->PutFile ($iorbase) == -1) { + print STDERR "ERROR: cannot set file <$client_iorfile>\n"; + $SV->Kill (); $SV->TimedWait (1); + exit 1; +} + +$client_status = $CL->SpawnWaitKill ($client->ProcessStartWaitInterval()); + +if ($client_status != 0) { + print STDERR "ERROR: client returned $client_status\n"; + $status = 1; +} + +$server_status = $SV->WaitKill ($server->ProcessStopWaitInterval()); + +if ($server_status != 0) { + print STDERR "ERROR: server returned $server_status\n"; + $status = 1; +} + +$server->GetStderrLog(); +$client->GetStderrLog(); + +$server->DeleteFile($server_iorfile); +$client->DeleteFile($client_iorfile); + +exit $status; diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp new file mode 100644 index 0000000000000..8f504aa3ba2a0 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp @@ -0,0 +1,42 @@ +#include "../../../examples/Simple/Simple_util.h" +#include "Echo_i.h" + +// This is the main driver program for the time and date server. + +int +ACE_TMAIN(int argc, ACE_TCHAR *argv[]) +{ + Server server; + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\n\tEcho server\n\n"))); + + try + { + if (server.init ("Echo", + argc, + argv) == -1) + return 1; + else + { + server.run (); + } + } + catch (const CORBA::UserException& userex) + { + userex._tao_print_exception ("User Exception"); + return -1; + } + catch (const CORBA::SystemException& sysex) + { + sysex._tao_print_exception ("System Exception"); + return -1; + } + catch (const ::CORBA::Exception &e) + { + e._tao_print_exception ("CORBA exception"); + return 1; + } + + return 0; +} From 9b80efcabd00153d77cc1561bfe57b6dd8529e9b Mon Sep 17 00:00:00 2001 From: Joachim Achtzehnter Date: Wed, 19 Aug 2020 15:28:32 -0700 Subject: [PATCH 2/7] Delete trailing whitespace --- .../Big_String_Sequence/Echo_Client_i.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp index d779208205dd4..ebebf875e33c0 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp @@ -31,24 +31,24 @@ Echo_Client_i::run (const char *name, try { Echo::List_var list = client_->return_list(); - std::cout << "Received list of length " + std::cout << "Received list of length " << list->length() << std::endl; if (list->length() != 2) { std::cout << "ERROR: Expected length 2, exiting..." << std::endl; - client_->shutdown (); + client_->shutdown (); return -1; } const char* value = (*list)[0].in(); size_t length = std::strlen(value); - std::cout << "First element has length " + std::cout << "First element has length " << length << std::endl; for (size_t n = 0; n < length; ++n) { if (value[n] != 'A') { std::cout << "ERROR: Character at position " << n - << " should be 'A', but is '" + << " should be 'A', but is '" << value[n] << "'" << std::endl; client_->shutdown (); return -1; @@ -56,13 +56,13 @@ Echo_Client_i::run (const char *name, } value = (*list)[1].in(); length = std::strlen(value); - std::cout << "Second element has length " + std::cout << "Second element has length " << length << std::endl; std::cout << "Value: " << value << std::endl; if (std::strcmp(value, "Hello World") != 0) { - std::cout << "ERROR: Expected \"Hello World\", exiting..." - << std::endl; + std::cout << "ERROR: Expected \"Hello World\", exiting..." + << std::endl; client_->shutdown (); return -1; } From 434993304c79e17cd1223ff6790522fff2a5df7b Mon Sep 17 00:00:00 2001 From: Joachim Achtzehnter Date: Thu, 20 Aug 2020 11:22:58 -0700 Subject: [PATCH 3/7] Added .gitignore, removed unneeded base project --- .../GIOP_Fragments/Big_String_Sequence/.gitignore | 10 ++++++++++ TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore b/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore new file mode 100644 index 0000000000000..dcc6a24a192e9 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore @@ -0,0 +1,10 @@ +.obj +.depend.Echo_Client +.depend.echo_idl +.depend.echo_idl_Idl1 +server_log.txt +client_log.txt +client +server +client_log.txt +server_log.txt diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc b/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc index ddd71d2634186..60e736c50f339 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc @@ -6,7 +6,7 @@ project(*idl): taoidldefaults { custom_only = 1 } -project(*Server): taoserver, namingexe, iortable, utils, avoids_corba_e_micro { +project(*Server): taoserver, namingexe, iortable, utils { exename = server after += *idl Source_Files { From df9c118b3763d9af6eab48c35bef387cfb80fe7a Mon Sep 17 00:00:00 2001 From: Joachim Achtzehnter Date: Thu, 20 Aug 2020 12:57:28 -0700 Subject: [PATCH 4/7] Added more generated files --- TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore b/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore index dcc6a24a192e9..7635eb6457368 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore @@ -1,5 +1,6 @@ .obj .depend.Echo_Client +.depend.Echo_Server .depend.echo_idl .depend.echo_idl_Idl1 server_log.txt From db94f76537a4c3cdb80907d585549bf983efe9f4 Mon Sep 17 00:00:00 2001 From: Joachim Achtzehnter Date: Wed, 26 Aug 2020 16:37:52 -0700 Subject: [PATCH 5/7] Rewritten to avoid including header from examples --- .../Big_String_Sequence/.gitignore | 2 - .../{echo.mpc => Big_String_Sequence.mpc} | 7 +- .../Big_String_Sequence/Echo.idl | 4 +- .../Big_String_Sequence/Echo_Client_i.cpp | 78 ------------- .../Big_String_Sequence/Echo_Client_i.h | 34 ------ .../Big_String_Sequence/Echo_i.cpp | 41 ++++--- .../Big_String_Sequence/Echo_i.h | 13 +-- .../Big_String_Sequence/README.md | 13 +-- .../Big_String_Sequence/client.cpp | 102 +++++++++++++++-- .../Big_String_Sequence/run_test.pl | 5 +- .../Big_String_Sequence/server.cpp | 107 ++++++++++++++---- 11 files changed, 213 insertions(+), 193 deletions(-) rename TAO/tests/GIOP_Fragments/Big_String_Sequence/{echo.mpc => Big_String_Sequence.mpc} (59%) delete mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp delete mode 100644 TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.h diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore b/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore index 7635eb6457368..9ec82bc74d998 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore @@ -7,5 +7,3 @@ server_log.txt client_log.txt client server -client_log.txt -server_log.txt diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Big_String_Sequence.mpc similarity index 59% rename from TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc rename to TAO/tests/GIOP_Fragments/Big_String_Sequence/Big_String_Sequence.mpc index 60e736c50f339..b46c33740a917 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Big_String_Sequence.mpc @@ -6,12 +6,11 @@ project(*idl): taoidldefaults { custom_only = 1 } -project(*Server): taoserver, namingexe, iortable, utils { +project(*Server): taoserver { exename = server after += *idl Source_Files { Echo_i.cpp - ../../../examples/Simple/Simple_util.cpp server.cpp EchoS.cpp EchoC.cpp @@ -20,12 +19,10 @@ project(*Server): taoserver, namingexe, iortable, utils { } } -project(*Client): taoclient, namingexe, iortable, utils { +project(*Client): taoclient { exename = client after += *IDL Source_Files { - Echo_Client_i.cpp - ../../../examples/Simple/Simple_util.cpp client.cpp EchoC.cpp } diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl index 28db1a83dade4..9dd09203d298d 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl @@ -6,11 +6,13 @@ interface Echo { // = TITLE // Defines an interface that encapsulates an operation that returns - // a string sequence. + // a string sequence, or a wstring sequence, respectively. typedef sequence List; + typedef sequence WList; List return_list (); + WList return_wlist (); oneway void shutdown (); }; diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp deleted file mode 100644 index ebebf875e33c0..0000000000000 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "Echo_Client_i.h" -#include "ace/Get_Opt.h" -#include "ace/Read_Buffer.h" -#include "ace/OS_NS_unistd.h" -#include -#include - -// This is the interface program that accesses the remote object - -// Constructor. -Echo_Client_i::Echo_Client_i (void) -{ - //no-op -} - -//Destructor. -Echo_Client_i::~Echo_Client_i (void) -{ - //no-op -} - -int -Echo_Client_i::run (const char *name, - int argc, - ACE_TCHAR *argv[]) -{ - // Initialize the client. - if (client_.init (name, argc, argv) == -1) - return -1; - - try - { - Echo::List_var list = client_->return_list(); - std::cout << "Received list of length " - << list->length() << std::endl; - if (list->length() != 2) - { - std::cout << "ERROR: Expected length 2, exiting..." << std::endl; - client_->shutdown (); - return -1; - } - const char* value = (*list)[0].in(); - size_t length = std::strlen(value); - std::cout << "First element has length " - << length << std::endl; - for (size_t n = 0; n < length; ++n) - { - if (value[n] != 'A') - { - std::cout << "ERROR: Character at position " << n - << " should be 'A', but is '" - << value[n] << "'" << std::endl; - client_->shutdown (); - return -1; - } - } - value = (*list)[1].in(); - length = std::strlen(value); - std::cout << "Second element has length " - << length << std::endl; - std::cout << "Value: " << value << std::endl; - if (std::strcmp(value, "Hello World") != 0) - { - std::cout << "ERROR: Expected \"Hello World\", exiting..." - << std::endl; - client_->shutdown (); - return -1; - } - client_->shutdown (); - } - catch (const CORBA::Exception& ex) - { - ex._tao_print_exception ("\n Exception in RMI"); - return -1; - } - - return 0; -} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.h b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.h deleted file mode 100644 index 82d35d53f187e..0000000000000 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.h +++ /dev/null @@ -1,34 +0,0 @@ -// -*- C++ -*- - -#ifndef ECHO_CLIENT_I_H -#define ECHO_CLIENT_I_H - -#include "../../../examples/Simple/Simple_util.h" -#include "EchoC.h" - -/** - * @class Echo_Client_i - * - * @brief Echo_Client interface subclass. - * - * This class implements the interface between the interface - * objects and the client . - */ -class Echo_Client_i -{ -public: - /// Constructor - Echo_Client_i (void); - - /// Destructor - ~Echo_Client_i (void); - - /// Execute the methods - int run (const char *, int, ACE_TCHAR **); - -private: - /// Instantiate the client object. - Client client_; -}; - -#endif /* TIME_CLIENT_I_H */ diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp index 058861f762461..0a1a818a548f9 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp @@ -3,24 +3,17 @@ // Constructor. -Echo_i::Echo_i (void) +Echo_i::Echo_i (CORBA::ORB_ptr o) + : orb_(o) { } // Destructor. -Echo_i::~Echo_i (void) +Echo_i::~Echo_i () { } -// Set the ORB pointer. - -void -Echo_i::orb (CORBA::ORB_ptr o) -{ - this->orb_ = CORBA::ORB::_duplicate (o); -} - // Return a list of strings. Echo::List * @@ -33,15 +26,13 @@ Echo_i::return_list () ACE_NEW_RETURN (tmp, Echo::List (2), 0); - // Pass ownership to the _var, pitty that ACE_NEW_RETURN cannot - // assign to T_vars directly. list = tmp; } list->length (2); // Just do something to get a 'big' list of strings. - std::string big(4 * 1024 * 1024, 'A'); + std::string big(4 * 1024, 'A'); std::string small("Hello World"); list[CORBA::ULong(0)] = CORBA::string_dup(big.c_str()); list[CORBA::ULong(1)] = CORBA::string_dup(small.c_str()); @@ -49,6 +40,30 @@ Echo_i::return_list () return list._retn (); } +Echo::WList * +Echo_i::return_wlist () +{ + Echo::WList_var list; + + { + Echo::WList *tmp = 0; + ACE_NEW_RETURN (tmp, + Echo::WList (2), + 0); + list = tmp; + } + + list->length (2); + + // Just do something to get a 'big' list of wide strings. + std::wstring big(4 * 1024, 'A'); + std::wstring small(17, 'B'); + list[CORBA::ULong(0)] = CORBA::wstring_dup(big.c_str()); + list[CORBA::ULong(1)] = CORBA::wstring_dup(small.c_str()); + + return list._retn (); +} + // Shutdown the server application. void diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h index 7e0822ebe264e..a7abf91134e4c 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h @@ -6,7 +6,6 @@ * * This class implements the Echo IDL interface. * - * @author Kirthika Parameswaran */ //============================================================================= @@ -21,29 +20,23 @@ * * @brief Echo Object Implementation * - * The object implementation performs the following functions: - * -- To return the string which needs to be displayed - * from the server. - * -- shuts down the server */ class Echo_i : public POA_Echo { public: /// Constructor. - Echo_i (void); + Echo_i (CORBA::ORB_ptr o); /// Destructor. virtual ~Echo_i (void); - /// Return the mesg string back from the server. + /// Return the result sequences to the cllient. virtual Echo::List *return_list (); + virtual Echo::WList *return_wlist (); /// Shutdown the server. virtual void shutdown (); - /// Set the ORB pointer. - void orb (CORBA::ORB_ptr o); - private: /// ORB pointer. CORBA::ORB_var orb_; diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md b/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md index 235eb9fb32ae4..55620b45305f0 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md @@ -2,18 +2,9 @@ ## Reproduces a bug when GIOP fragmentation is used The server returns a string sequence with two elements, the first is a -long 4MB string with repeating character 'A', the second element is +long 4kB string with repeating character 'A', the second element is the string "Hello World". If one removes the command line parameters -`-ORBMaxMessageSize 1048576` from `run_test.pl` everything +`-ORBMaxMessageSize 1024` from `run_test.pl` everything works as expected, but with these settings, which cause GIOP fragmentation, the client receives an empty string as the second element of the sequence. - -We discovered problems in a more complicated application when big -sequences are returned, often the client encountering -`CORBA::MARSHAL` or `CORBA::COMM_FAILURE` exceptions. In one -case, it worked if the sequence contained a single element, even if -big, but a small second element caused client exceptions. The complex -application encountered problems with big sequences even without the -`-ORBMaxMessageSize` parameter, but problems start at smaller -sizes if it is used. \ No newline at end of file diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp index d3851527028c0..ca3aca0fae8ad 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp @@ -1,19 +1,97 @@ -# include "Echo_Client_i.h" +#include "EchoC.h" +#include "ace/Get_Opt.h" +#include -// The client program for the application. +const ACE_TCHAR *ior = ACE_TEXT ("file://test.ior"); + +int parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("f:")); + int c; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'f': + ior = get_opts.opt_arg (); + break; + + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s " + "-f " + "\n", + argv [0]), + -1); + } + // Indicates successful parsing of the command line + return 0; +} int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) -{ - Echo_Client_i client; +{ + try + { + CORBA::ORB_var orb = CORBA::ORB_init (argc, argv); + + if (parse_args (argc, argv) != 0) + return -1; + + CORBA::Object_var tmp = orb->string_to_object(ior); + + Echo_var echo = Echo::_narrow(tmp.in ()); - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("\nEcho client\n\n"))); + if (CORBA::is_nil (echo.in ())) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Nil Echo reference <%s>\n", + ior), + -1); + } + + Echo::List_var list = echo->return_list(); + + ACE_DEBUG ((LM_DEBUG, + "Received list of length %u\n", + list->length())); + if (list->length() != 2) + { + ACE_ERROR_RETURN ((LM_ERROR, "Expected length 2\n"), -1); + } + const char* value = (*list)[0].in(); + size_t length = std::strlen(value); + ACE_DEBUG ((LM_DEBUG, + "First element has length %u\n", + length)); + for (size_t n = 0; n < length; ++n) + { + if (value[n] != 'A') + { + ACE_ERROR_RETURN ((LM_ERROR, + "Character at position %u should be 'A'," + " but is '%c'\n", value[n]), -1); + } + } + value = (*list)[1].in(); + length = std::strlen(value); + ACE_DEBUG ((LM_DEBUG, + "Second element has length %u, value: %s\n", + length, value)); + if (std::strcmp(value, "Hello World") != 0) + { + ACE_ERROR_RETURN ((LM_ERROR, "Expected \"Hello World\""), -1); + } + + echo->shutdown (); + orb->destroy (); + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("Exception caught:"); + return 1; + } - if (client.run ("Echo", - argc, - argv) == -1) - return -1; - else - return 0; + return 0; } diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl b/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl index 6d6d869d2a46c..329c2ea3ff368 100755 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl @@ -22,11 +22,12 @@ my $iorbase = "server.ior"; my $server_iorfile = $server->LocalFile ($iorbase); my $client_iorfile = $client->LocalFile ($iorbase); + $server->DeleteFile($iorbase); $client->DeleteFile($iorbase); -$SV = $server->CreateProcess ("server", "-ORBMaxMessageSize 1048576 -ORBdebuglevel $debug_level -ORBLogFile server_log.txt -o $server_iorfile"); -$CL = $client->CreateProcess ("client", "-ORBdebuglevel $debug_level -ORBLogFile client_log.txt -f $client_iorfile -x"); +$SV = $server->CreateProcess ("server", "-ORBMaxMessageSize 1024 -ORBdebuglevel $debug_level -o $server_iorfile"); +$CL = $client->CreateProcess ("client", "-ORBdebuglevel $debug_level -f file://$client_iorfile"); $server_status = $SV->Spawn (); if ($server_status != 0) { diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp index 8f504aa3ba2a0..4ff8e031dc06f 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp @@ -1,40 +1,97 @@ -#include "../../../examples/Simple/Simple_util.h" #include "Echo_i.h" +#include "ace/Get_Opt.h" +#include "ace/OS_NS_stdio.h" -// This is the main driver program for the time and date server. +const ACE_TCHAR *ior_output_file = ACE_TEXT ("test.ior"); int -ACE_TMAIN(int argc, ACE_TCHAR *argv[]) +parse_args (int argc, ACE_TCHAR *argv[]) { - Server server; + ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("o:")); + int c; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'o': + ior_output_file = get_opts.opt_arg (); + break; - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("\n\tEcho server\n\n"))); + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s " + "-o " + "\n", + argv [0]), + -1); + } + // Indicates successful parsing of the command line + return 0; +} +int +ACE_TMAIN(int argc, ACE_TCHAR *argv[]) +{ try { - if (server.init ("Echo", - argc, - argv) == -1) + CORBA::ORB_var orb = + CORBA::ORB_init (argc, argv); + + CORBA::Object_var poa_object = + orb->resolve_initial_references("RootPOA"); + + PortableServer::POA_var root_poa = + PortableServer::POA::_narrow (poa_object.in ()); + + if (CORBA::is_nil (root_poa.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Panic: nil RootPOA\n"), + 1); + + PortableServer::POAManager_var poa_manager = root_poa->the_POAManager (); + + if (parse_args (argc, argv) != 0) return 1; - else - { - server.run (); - } - } - catch (const CORBA::UserException& userex) - { - userex._tao_print_exception ("User Exception"); - return -1; - } - catch (const CORBA::SystemException& sysex) - { - sysex._tao_print_exception ("System Exception"); - return -1; + + Echo_i *echo_impl = 0; + ACE_NEW_RETURN (echo_impl, + Echo_i (orb.in ()), + 1); + PortableServer::ServantBase_var owner_transfer(echo_impl); + + PortableServer::ObjectId_var id = + root_poa->activate_object (echo_impl); + + CORBA::Object_var object = root_poa->id_to_reference (id.in ()); + + Echo_var echo = Echo::_narrow (object.in ()); + + CORBA::String_var ior = orb->object_to_string (echo.in ()); + + // Output the IOR to the + FILE* output_file = ACE_OS::fopen (ior_output_file, "w"); + if (output_file == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Cannot open output file for writing IOR: %s\n", + ior_output_file), + 1); + ACE_OS::fprintf (output_file, "%s", ior.in ()); + ACE_OS::fclose (output_file); + + poa_manager->activate (); + + orb->run (); + + ACE_DEBUG ((LM_DEBUG, "(%P|%t) server - event loop finished\n")); + + root_poa->destroy (1, 1); + + orb->destroy (); } - catch (const ::CORBA::Exception &e) + catch (const CORBA::Exception& ex) { - e._tao_print_exception ("CORBA exception"); + ex._tao_print_exception ("Exception caught:"); return 1; } From 477f0dab0b7feee0bedd3afed629f5ed0937d7cd Mon Sep 17 00:00:00 2001 From: Joachim Achtzehnter Date: Wed, 26 Aug 2020 16:42:18 -0700 Subject: [PATCH 6/7] Removed trailing white space --- TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp index ca3aca0fae8ad..d78b56841e6bc 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp @@ -31,7 +31,7 @@ int parse_args (int argc, ACE_TCHAR *argv[]) int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) -{ +{ try { CORBA::ORB_var orb = CORBA::ORB_init (argc, argv); @@ -50,9 +50,9 @@ ACE_TMAIN(int argc, ACE_TCHAR *argv[]) ior), -1); } - + Echo::List_var list = echo->return_list(); - + ACE_DEBUG ((LM_DEBUG, "Received list of length %u\n", list->length())); @@ -83,7 +83,7 @@ ACE_TMAIN(int argc, ACE_TCHAR *argv[]) { ACE_ERROR_RETURN ((LM_ERROR, "Expected \"Hello World\""), -1); } - + echo->shutdown (); orb->destroy (); } From 259367ebea5fe5b875d42d0e431f0e7171a39aa5 Mon Sep 17 00:00:00 2001 From: Joachim Achtzehnter Date: Fri, 11 Sep 2020 18:53:25 -0700 Subject: [PATCH 7/7] Removed use of std namespace (really?) --- .../Big_String_Sequence/Echo_i.cpp | 28 +++++++++++++------ .../Big_String_Sequence/client.cpp | 16 +++++++++-- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp index 0a1a818a548f9..bd1e6203b2170 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp @@ -1,6 +1,7 @@ -#include #include "Echo_i.h" +enum { BIG_LENGTH = 4 * 1024 }; + // Constructor. Echo_i::Echo_i (CORBA::ORB_ptr o) @@ -32,10 +33,13 @@ Echo_i::return_list () list->length (2); // Just do something to get a 'big' list of strings. - std::string big(4 * 1024, 'A'); - std::string small("Hello World"); - list[CORBA::ULong(0)] = CORBA::string_dup(big.c_str()); - list[CORBA::ULong(1)] = CORBA::string_dup(small.c_str()); + CORBA::Char big[BIG_LENGTH + 1]; + for (int i = 0; i < BIG_LENGTH; ++i) + big[i] = 'A'; + big[BIG_LENGTH] = 0; + CORBA::Char small[] = "Hello World"; + list[CORBA::ULong(0)] = CORBA::string_dup(big); + list[CORBA::ULong(1)] = CORBA::string_dup(small); return list._retn (); } @@ -56,10 +60,16 @@ Echo_i::return_wlist () list->length (2); // Just do something to get a 'big' list of wide strings. - std::wstring big(4 * 1024, 'A'); - std::wstring small(17, 'B'); - list[CORBA::ULong(0)] = CORBA::wstring_dup(big.c_str()); - list[CORBA::ULong(1)] = CORBA::wstring_dup(small.c_str()); + CORBA::WChar big[BIG_LENGTH + 1]; + for (int i = 0; i < BIG_LENGTH; ++i) + big[i] = 'A'; + big[BIG_LENGTH] = 0; + CORBA::WChar small[17 + 1]; + for (int i = 0; i < 17; ++i) + small[i] = 'B'; + small[17] = 0; + list[CORBA::ULong(0)] = CORBA::wstring_dup(big); + list[CORBA::ULong(1)] = CORBA::wstring_dup(small); return list._retn (); } diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp index d78b56841e6bc..6cbd0fe6b6591 100644 --- a/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp @@ -61,7 +61,7 @@ ACE_TMAIN(int argc, ACE_TCHAR *argv[]) ACE_ERROR_RETURN ((LM_ERROR, "Expected length 2\n"), -1); } const char* value = (*list)[0].in(); - size_t length = std::strlen(value); + size_t length = strlen(value); ACE_DEBUG ((LM_DEBUG, "First element has length %u\n", length)); @@ -75,15 +75,25 @@ ACE_TMAIN(int argc, ACE_TCHAR *argv[]) } } value = (*list)[1].in(); - length = std::strlen(value); + length = strlen(value); ACE_DEBUG ((LM_DEBUG, "Second element has length %u, value: %s\n", length, value)); - if (std::strcmp(value, "Hello World") != 0) + if (strcmp(value, "Hello World") != 0) { ACE_ERROR_RETURN ((LM_ERROR, "Expected \"Hello World\""), -1); } + Echo::WList_var wlist = echo->return_wlist(); + + ACE_DEBUG ((LM_DEBUG, + "Received wide list of length %u\n", + wlist->length())); + if (wlist->length() != 2) + { + ACE_ERROR_RETURN ((LM_ERROR, "Expected length 2\n"), -1); + } + echo->shutdown (); orb->destroy (); }