Skip to content

Commit fcdef8f

Browse files
authored
Merge pull request #1359 from DOCGroup/repro-fragmentation-issue
Repro problem with fragmented GIOP messages
2 parents 67aa234 + daa794e commit fcdef8f

10 files changed

Lines changed: 472 additions & 0 deletions

File tree

TAO/bin/tao_orb_tests.lst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ TAO/tests/Native_Exceptions/run_test.pl:
434434
TAO/tests/Servant_To_Reference_Test/run_test.pl: !MINIMUM !CORBA_E_COMPACT !CORBA_E_MICRO !ST
435435
TAO/tests/Sequence_Unit_Tests/run_test.pl:
436436
TAO/tests/Typedef_String_Array/run_test.pl:
437+
TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl: !FIXED_BUGS_ONLY
437438
TAO/tests/GIOP_Fragments/PMB_With_Fragments/run_test.pl: !CORBA_E_MICRO
438439
TAO/tests/CodeSets/simple/run_test.pl: !GIOP10 !STATIC
439440
TAO/tests/Hang_Shutdown/run_test.pl: !ST !ACE_FOR_TAO
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.obj
2+
.depend.Echo_Client
3+
.depend.Echo_Server
4+
.depend.echo_idl
5+
.depend.echo_idl_Idl1
6+
server_log.txt
7+
client_log.txt
8+
client
9+
server
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// -*- MPC -*-
2+
project(*idl): taoidldefaults {
3+
IDL_Files {
4+
Echo.idl
5+
}
6+
custom_only = 1
7+
}
8+
9+
project(*Server): taoserver {
10+
exename = server
11+
after += *idl
12+
Source_Files {
13+
Echo_i.cpp
14+
server.cpp
15+
EchoS.cpp
16+
EchoC.cpp
17+
}
18+
IDL_Files {
19+
}
20+
}
21+
22+
project(*Client): taoclient {
23+
exename = client
24+
after += *idl
25+
Source_Files {
26+
client.cpp
27+
EchoC.cpp
28+
}
29+
IDL_Files {
30+
}
31+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
interface Echo
2+
{
3+
// Defines an interface that encapsulates an operation that returns
4+
// a string sequence, or a wstring sequence, respectively.
5+
6+
typedef sequence<string> List;
7+
typedef sequence<wstring> WList;
8+
9+
List return_list ();
10+
WList return_wlist ();
11+
12+
oneway void shutdown ();
13+
};
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#include "Echo_i.h"
2+
3+
constexpr size_t BIG_LENGTH = 4 * 1024;
4+
5+
// Constructor.
6+
7+
Echo_i::Echo_i (CORBA::ORB_ptr o)
8+
: orb_(o)
9+
{
10+
}
11+
12+
// Return a list of strings.
13+
Echo::List *
14+
Echo_i::return_list ()
15+
{
16+
Echo::List_var list;
17+
18+
{
19+
Echo::List *tmp {};
20+
ACE_NEW_RETURN (tmp,
21+
Echo::List (2),
22+
{});
23+
list = tmp;
24+
}
25+
26+
list->length (2);
27+
28+
// Just do something to get a 'big' list of strings.
29+
CORBA::Char big[BIG_LENGTH + 1];
30+
for (size_t i = 0; i < BIG_LENGTH; ++i)
31+
big[i] = 'A';
32+
big[BIG_LENGTH] = 0;
33+
list[CORBA::ULong(0)] = CORBA::string_dup(big);
34+
list[CORBA::ULong(1)] = CORBA::string_dup("Hello World");
35+
36+
return list._retn ();
37+
}
38+
39+
Echo::WList *
40+
Echo_i::return_wlist ()
41+
{
42+
Echo::WList_var list;
43+
44+
{
45+
Echo::WList *tmp {};
46+
ACE_NEW_RETURN (tmp,
47+
Echo::WList (2),
48+
{});
49+
list = tmp;
50+
}
51+
52+
list->length (2);
53+
54+
// Just do something to get a 'big' list of wide strings.
55+
CORBA::WChar big[BIG_LENGTH + 1];
56+
for (size_t i = 0; i < BIG_LENGTH; ++i)
57+
big[i] = 'A';
58+
big[BIG_LENGTH] = 0;
59+
CORBA::WChar small[17 + 1];
60+
for (size_t i = 0; i < 17; ++i)
61+
small[i] = 'B';
62+
small[17] = 0;
63+
list[CORBA::ULong(0)] = CORBA::wstring_dup(big);
64+
list[CORBA::ULong(1)] = CORBA::wstring_dup(small);
65+
66+
return list._retn ();
67+
}
68+
69+
// Shutdown the server application.
70+
71+
void
72+
Echo_i::shutdown ()
73+
{
74+
ACE_DEBUG ((LM_DEBUG,
75+
ACE_TEXT ("\nThe echo server is shutting down\n")));
76+
77+
// Instruct the ORB to shutdown.
78+
this->orb_->shutdown ();
79+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// -*- C++ -*-
2+
3+
//=============================================================================
4+
/**
5+
* @file Echo_i.h
6+
*
7+
* This class implements the Echo IDL interface.
8+
*
9+
*/
10+
//=============================================================================
11+
12+
13+
#ifndef ECHO_I_H
14+
#define ECHO_I_H
15+
16+
#include "EchoS.h"
17+
18+
/**
19+
* @class Echo_i
20+
*
21+
* @brief Echo Object Implementation
22+
*
23+
*/
24+
class Echo_i : public POA_Echo
25+
{
26+
public:
27+
/// Constructor.
28+
Echo_i (CORBA::ORB_ptr o);
29+
30+
/// Destructor.
31+
~Echo_i () override = default;
32+
33+
/// Return the result sequences to the cllient.
34+
Echo::List *return_list () override;
35+
Echo::WList *return_wlist () override;
36+
37+
/// Shutdown the server.
38+
void shutdown () override;
39+
40+
private:
41+
/// ORB pointer.
42+
CORBA::ORB_var orb_;
43+
44+
void operator= (const Echo_i&) = delete;
45+
};
46+
47+
#endif /* ECHO_I_H */
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# TAO GIOP Fragmentation Bug
2+
## Reproduces a bug when GIOP fragmentation is used
3+
4+
The server returns a string sequence with two elements, the first is a
5+
long 4kB string with repeating character 'A', the second element is
6+
the string "Hello World". If one removes the command line parameters
7+
`-ORBMaxMessageSize 1024` from `run_test.pl` everything
8+
works as expected, but with these settings, which cause GIOP
9+
fragmentation, the client receives an empty string as the second
10+
element of the sequence.
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#include "EchoC.h"
2+
#include "ace/Get_Opt.h"
3+
#include <cstring>
4+
5+
const ACE_TCHAR *ior = ACE_TEXT ("file://test.ior");
6+
7+
int parse_args (int argc, ACE_TCHAR *argv[])
8+
{
9+
ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("f:"));
10+
int c;
11+
12+
while ((c = get_opts ()) != -1)
13+
switch (c)
14+
{
15+
case 'f':
16+
ior = get_opts.opt_arg ();
17+
break;
18+
19+
case '?':
20+
default:
21+
ACE_ERROR_RETURN ((LM_ERROR,
22+
"usage: %s "
23+
"-f <ior> "
24+
"\n",
25+
argv [0]),
26+
-1);
27+
}
28+
// Indicates successful parsing of the command line
29+
return 0;
30+
}
31+
32+
int
33+
ACE_TMAIN(int argc, ACE_TCHAR *argv[])
34+
{
35+
try
36+
{
37+
CORBA::ORB_var orb = CORBA::ORB_init (argc, argv);
38+
39+
if (parse_args (argc, argv) != 0)
40+
return -1;
41+
42+
CORBA::Object_var tmp = orb->string_to_object(ior);
43+
44+
Echo_var echo = Echo::_narrow(tmp.in ());
45+
46+
if (CORBA::is_nil (echo.in ()))
47+
{
48+
ACE_ERROR_RETURN ((LM_ERROR,
49+
"Nil Echo reference <%s>\n",
50+
ior),
51+
-1);
52+
}
53+
54+
Echo::List_var list = echo->return_list();
55+
56+
ACE_DEBUG ((LM_DEBUG,
57+
"Received list of length %u\n",
58+
list->length()));
59+
if (list->length() != 2)
60+
{
61+
ACE_ERROR_RETURN ((LM_ERROR, "Expected length 2\n"), -1);
62+
}
63+
const char* value = (*list)[0].in();
64+
size_t length = std::strlen(value);
65+
ACE_DEBUG ((LM_DEBUG,
66+
"First element has length %u\n",
67+
length));
68+
for (size_t n = 0; n < length; ++n)
69+
{
70+
if (value[n] != 'A')
71+
{
72+
ACE_ERROR_RETURN ((LM_ERROR,
73+
"Character at position %u should be 'A',"
74+
" but is '%c'\n", value[n]), -1);
75+
}
76+
}
77+
value = (*list)[1].in();
78+
length = std::strlen(value);
79+
ACE_DEBUG ((LM_DEBUG,
80+
"Second element has length %u, value: <%C>\n",
81+
length, value));
82+
if (strcmp(value, "Hello World") != 0)
83+
{
84+
ACE_ERROR_RETURN ((LM_ERROR, "Expected \"Hello World\""), -1);
85+
}
86+
87+
Echo::WList_var wlist = echo->return_wlist();
88+
89+
ACE_DEBUG ((LM_DEBUG,
90+
"Received wide list of length %u\n",
91+
wlist->length()));
92+
if (wlist->length() != 2)
93+
{
94+
ACE_ERROR_RETURN ((LM_ERROR, "Expected length 2\n"), -1);
95+
}
96+
97+
echo->shutdown ();
98+
orb->destroy ();
99+
}
100+
catch (const CORBA::Exception& ex)
101+
{
102+
ex._tao_print_exception ("Exception caught:");
103+
return 1;
104+
}
105+
106+
return 0;
107+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
2+
& eval 'exec perl -S $0 $argv:q'
3+
if 0;
4+
5+
# -*- perl -*-
6+
7+
use lib "$ENV{ACE_ROOT}/bin";
8+
use PerlACE::TestTarget;
9+
10+
$status = 0;
11+
$debug_level = '0';
12+
13+
foreach $i (@ARGV) {
14+
if ($i eq '-debug') {
15+
$debug_level = '10';
16+
}
17+
}
18+
19+
my $server = PerlACE::TestTarget::create_target (1) || die "Create target 1 failed\n";
20+
my $client = PerlACE::TestTarget::create_target (2) || die "Create target 2 failed\n";
21+
22+
my $iorbase = "server.ior";
23+
my $server_iorfile = $server->LocalFile ($iorbase);
24+
my $client_iorfile = $client->LocalFile ($iorbase);
25+
26+
$server->DeleteFile($iorbase);
27+
$client->DeleteFile($iorbase);
28+
29+
$SV = $server->CreateProcess ("server", "-ORBMaxMessageSize 1024 -ORBdebuglevel $debug_level -o $server_iorfile");
30+
$CL = $client->CreateProcess ("client", "-ORBdebuglevel $debug_level -f file://$client_iorfile");
31+
$server_status = $SV->Spawn ();
32+
33+
if ($server_status != 0) {
34+
print STDERR "ERROR: server returned $server_status\n";
35+
exit 1;
36+
}
37+
38+
if ($server->WaitForFileTimed ($iorbase,
39+
$server->ProcessStartWaitInterval()) == -1) {
40+
print STDERR "ERROR: cannot find file <$server_iorfile>\n";
41+
$SV->Kill (); $SV->TimedWait (1);
42+
exit 1;
43+
}
44+
45+
if ($server->GetFile ($iorbase) == -1) {
46+
print STDERR "ERROR: cannot retrieve file <$server_iorfile>\n";
47+
$SV->Kill (); $SV->TimedWait (1);
48+
exit 1;
49+
}
50+
if ($client->PutFile ($iorbase) == -1) {
51+
print STDERR "ERROR: cannot set file <$client_iorfile>\n";
52+
$SV->Kill (); $SV->TimedWait (1);
53+
exit 1;
54+
}
55+
56+
$client_status = $CL->SpawnWaitKill ($client->ProcessStartWaitInterval());
57+
58+
if ($client_status != 0) {
59+
print STDERR "ERROR: client returned $client_status\n";
60+
$status = 1;
61+
}
62+
63+
$server_status = $SV->WaitKill ($server->ProcessStopWaitInterval());
64+
65+
if ($server_status != 0) {
66+
print STDERR "ERROR: server returned $server_status\n";
67+
$status = 1;
68+
}
69+
70+
$server->GetStderrLog();
71+
$client->GetStderrLog();
72+
73+
$server->DeleteFile($server_iorfile);
74+
$client->DeleteFile($client_iorfile);
75+
76+
exit $status;

0 commit comments

Comments
 (0)