using namespace CppUnit;
using namespace libt2n;
-namespace
+namespace reentrant
{
command_server *global_server = NULL;
+int fork_count = 3;
+int requests_per_child = 100;
+int all_requests = (2 << (fork_count-1)) * requests_per_child;
+
+int seen_client_requests = 0;
+
string testfunc(const string& str)
{
string ret;
// call handle, eventually reentrant
if (global_server)
- global_server->handle(1000);
+ global_server->handle(10000);
+
+ ++seen_client_requests;
return ret;
}
public:
testfunc_res()
- { }
+ {
+ }
testfunc_res(const string& str)
{
public:
testfunc_cmd()
- { }
+ {
+ }
testfunc_cmd(const string& str)
{
}
+
#include <boost/serialization/export.hpp>
-BOOST_CLASS_EXPORT(testfunc_cmd)
-BOOST_CLASS_EXPORT(testfunc_res)
+BOOST_CLASS_EXPORT(reentrant::testfunc_cmd)
+BOOST_CLASS_EXPORT(reentrant::testfunc_res)
+
+using namespace reentrant;
class test_reentrant : public TestFixture
{
CPPUNIT_TEST_SUITE_END();
- pid_t child_pid;
-
public:
void setUp()
void ReentrantServer()
{
- switch(child_pid=fork())
+ switch(fork())
{
case -1:
{
// child
{
// wait till server is up
- sleep(3);
+ sleep(2);
- // we want 8 identical childs hammering the server
- fork();
- fork();
- fork();
+ // hammer the server
+ for (int i = 0; i < fork_count; i++)
+ fork();
- for (int i=0; i < 100; i++)
+ try
{
- socket_client_connection sc("./socket");
- command_client cc(&sc);
-
- result_container rc;
- cc.send_command(new testfunc_cmd("hello"),rc);
-
- string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
-
- CPPUNIT_ASSERT_EQUAL(string("hello, testfunc() was here"),ret);
+ for (int i=0; i < requests_per_child; i++)
+ {
+ socket_client_connection sc("./socket");
+ // sc.set_logging(&cerr,debug);
+ command_client cc(&sc);
+
+ result_container rc;
+ cc.send_command(new testfunc_cmd("hello"),rc);
+
+ testfunc_res *res = dynamic_cast<testfunc_res*>(rc.get_result());
+ if (res)
+ {
+ string ret = res->get_data();
+ if (ret != "hello, testfunc() was here")
+ std::cout << "ERROR reentrant server testfunc_res failed, res: \"" << ret << "\"\n";
+ }
+ else
+ {
+ std::cout << "ERROR result from reentrant server empty (" << rc.get_result() << ")\n";
+ }
+ }
+ } catch (exception &e)
+ {
+ cerr << "caught exception: " << e.what() << endl;
+ } catch(...)
+ {
+ std::cerr << "exception in child. ignoring\n";
}
// don't call atexit and stuff
default:
// parent
{
+ // don't kill us on broken pipe
+ signal(SIGPIPE, SIG_IGN);
+
socket_server ss("./socket");
command_server cs(ss);
global_server=&cs;
- // max 10 sec
- long long maxtime=5000000;
- while(maxtime > 0)
- cs.handle(maxtime,&maxtime);
-
+ // Wait until all requests have successed
+ int safety_check = 0;
+ while (seen_client_requests < all_requests)
+ {
+ ++safety_check;
+ if (safety_check > 10) {
+ std::cerr << "reached safety check, aborting.\n";
+ break;
+ }
+
+ long long maxtime=1000000;
+ while(maxtime > 0)
+ cs.handle(maxtime,&maxtime);
+ }
+
global_server = NULL;
}
// we are still alive, everything is ok
- CPPUNIT_ASSERT_EQUAL(1,1);
+ CPPUNIT_ASSERT_EQUAL(all_requests, seen_client_requests);
}
}