Project

General

Profile

WServer instantiation in GTest environment

Added by Matteo Sciolla over 9 years ago

Hi

I think I wrongly reported this as issue here http://redmine.webtoolkit.eu/projects/wt/issues

Maybe it's better to ask my question here do I reported my message:

I'm developing a simple REST service using Wt WServer and WClient classes.

Here is my problem: if I instantiate a WServer in a GTest environment (in my continuous integration suite), I'm not able to set http options.

This simple code bring me to a segfault error (the same code, outside the test env, works fine):

@std::vector<const char*> myArgs;

myArgs.push_back("fsserver");

myArgs.push_back("---docroot");

myArgs.push_back(".");

myArgs.push_back("---http-address");

myArgs.push_back("0.0.0.0");

myArgs.push_back("---http-port");

myArgs.push_back("8888");

Wt::WServer myServer(myArgs0);

myServer.setServerConfiguration(myArgs.size(),

const_cast<char>(myArgs.data()),

WTHTTP_CONFIGURATION);@

Here you have the stack trace

#0  0x00007fad2fe7f10d in Wt::WServer::setServerConfiguration (this=0x7fff23482830, argc=7, argv=0x2d7a730, serverConfigurationFile=...) at /root/Software/Installed/wt-3.3.1/src/http/WServer.C:110
#1  0x00007fad3010d680 in restful::WtRestServer::WtRestServer (this=0x7fff23482830, aParams=...) at /spare/msciolla/workspace/test/wtrestserver.cpp:20
#2  0x00007fad3a1abc5b in TestWtRestServer_test_manage_remote_file_Test::TestBody (this=0x2d7ab80) at /spare/msciolla/workspace/test/testwtrestserver.cpp:64
#3  0x00007fad3196b322 in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void> (object=0x2d7ab80, method=&virtual testing::Test::TestBody(), 
    location=0x7fad3197820b "the test body") at /spare/msciolla/workspace/test/../externals/GMock/gtest/src/gtest.cc:2078
#4  0x00007fad31966bfe in testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void> (object=0x2d7ab80, method=&virtual testing::Test::TestBody(), location=0x7fad3197820b "the test body")
    at /spare/msciolla/workspace/test/../externals/GMock/gtest/src/gtest.cc:2114
#5  0x00007fad3194e915 in testing::Test::Run (this=0x2d7ab80) at /spare/msciolla/workspace/test/../externals/GMock/gtest/src/gtest.cc:2151
#6  0x00007fad3194f0a3 in testing::TestInfo::Run (this=0x2ce7200) at /spare/msciolla/workspace/test/../externals/GMock/gtest/src/gtest.cc:2326
#7  0x00007fad3194f6de in testing::TestCase::Run (this=0x2ce7300) at /spare/msciolla/workspace/test/../externals/GMock/gtest/src/gtest.cc:2444
#8  0x00007fad31955e99 in testing::internal::UnitTestImpl::RunAllTests (this=0x2cac5b0)
    at /spare/msciolla/workspace/test/../externals/GMock/gtest/src/gtest.cc:4315
#9  0x00007fad3196c167 in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x2cac5b0, 
    method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x7fad31955bfc <testing::internal::UnitTestImpl::RunAllTests()>, 
    location=0x7fad31978a60 "auxiliary test code (environments or event listeners)") at /spare/msciolla/workspace/test/../externals/GMock/gtest/src/gtest.cc:2078
#10 0x00007fad31967986 in testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x2cac5b0, 
    method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x7fad31955bfc <testing::internal::UnitTestImpl::RunAllTests()>, 
    location=0x7fad31978a60 "auxiliary test code (environments or event listeners)") at /spare/msciolla/workspace/test/../externals/GMock/gtest/src/gtest.cc:2114
#11 0x00007fad31954c25 in testing::UnitTest::Run (this=0x7fad31ba1080 <testing::UnitTest::GetInstance()::instance>)
    at /spare/msciolla/test/../externals/GMock/gtest/src/gtest.cc:3929
#12 0x0000000000c1d973 in RUN_ALL_TESTS () at /spare/msciolla/workspace/test/../externals/GMock/gtest/include/gtest/gtest.h:2288
#13 0x0000000000c1d671 in main (argc=1, argv=0x7fff23483038) at /spare/msciolla/workspace/test/TestUnit/testunit.cpp:59

Do you know the reason of the different behaviour?

Thanks in advance


Replies (10)

RE: WServer instantiation in GTest environment - Added by Alan Finley over 9 years ago

Does it still crash if your replace std::vector<const char*> with a raw pointer char**?

RE: WServer instantiation in GTest environment - Added by Matteo Sciolla over 9 years ago

modified like this:

const char** myArgs = static_cast<const char**>(malloc(7*sizeof(char*)));
myArgs[0] = "fsserver";
myArgs[1] = "--docroot";
myArgs[2] = ".";
myArgs[3] = "--http-address";
myArgs[4] = "0.0.0.0";
myArgs[5] = "--http-port";
myArgs[6] = "8888";

Wt::WServer myServer(myArgs[0]);
myServer.setServerConfiguration(sizeof(myArgs), const_cast<char**>(myArgs), WTHTTP_CONFIGURATION);

it still crashes

RE: WServer instantiation in GTest environment - Added by Eivind Midtgård over 9 years ago

The complete command line you create is wrong. For example, the sizeof(myArgs) is not 7, but 4, and the argv array is not correctly constructed.

But before I show a possible implementation, let me ask why you don't just pass the command line when you start the program and let the OS and C runtime handle it. This

yourprogram fsserver --docroot .  --http-address "0.0.0.0" -http-port 8080

will do what you want.

You could make the command line like this (probably wanting to change the name of f to 'argbuilder'):

    char* args[7];
    auto f = [&](int n, const std::string& s) {args[n] = new char[s.length() + 1]; strcpy(args[n], s.c_str());};
    int ix = 0;
    f(ix++, "fsserver");
    f(ix++, "--docroot");
    f(ix++, ".");
    f(ix++, "--http-address");
    f(ix++, "0.0.0.0");
    f(ix++, "--http-port");
    f(ix++, "8888");

    Wt::WServer myServer(args[0]);
    myServer.setServerConfiguration(7, args, WTHTTP_CONFIGURATION);

    // Somewhere
    for (auto it = std::begin(args); it != std::end(args); ++it)
        delete [] *it;

Regards,

Eivind

RE: WServer instantiation in GTest environment - Added by Matteo Sciolla over 9 years ago

It fix the problem thanks! So dumb to confuse array and pointer, forgive me!

I don't pass the command line because I'm running a large suite of several automatic tests so I don't have any command line to pass to :)

Thanks for your help!

RE: WServer instantiation in GTest environment - Added by Matteo Sciolla over 9 years ago

well, nevermind, it still crash :(

RE: WServer instantiation in GTest environment - Added by Thomas Saquet over 9 years ago

Hello Matteo,

Same problem here, fixed copying how it is done in the test files of Wt.

You can find the code here around the line 108 :

https://github.com/kdeforche/wt/blob/master/test/http/HttpClientServerTest.C

Regards,

Thomas

RE: WServer instantiation in GTest environment - Added by Matteo Sciolla over 9 years ago

thanks Thomas, I'll try tomorrow morning

Matteo

RE: WServer instantiation in GTest environment - Added by Matteo Sciolla over 9 years ago

don't hate me, I'm adding some more spice :)

I have a segfault iff my WServer derived class has a container (e.g.std::vector) allocated on stack as attribute. If it has a primitive, inf or float, all is fine. My current workaround is to allocate that container on the heap.

I would like to remember that I'm having this behaviour when I insert my code in my test suite, based on gtest library

Matteo

RE: WServer instantiation in GTest environment - Added by Matteo Sciolla over 9 years ago

I found the reason of the strange behaviour!!! The problem is in the wt library link order: my executable needs libwt, libwthttp and libwttest. The problem raises iff libwttest is linked before libhttp. I briefly watched exported symbols by the two libraries founding there are some WServer symbols common between them. It was already known this link order constraints? Did I miss some directive?

Matteo

RE: WServer instantiation in GTest environment - Added by Koen Deforche over 9 years ago

Hey Matteo,

Ah, indeed libwttest and libwthttp are not intended to be used together. That's a good observation and something that is indeed lacking in the documentation.

But it is indeed a silly constraint that this is being imposed by the library. In fact, I believe you're right to assume that you indeed can have both libraries together if the WServer implementation of libwthttp is being used. I'm not sure though to what extent this depends on a linker's (unspecified) behavior.

Regards,

koen

    (1-10/10)