Solarus-Games English Forum

Solarus => Development => Topic started by: mdblabs on October 11, 2017, 12:13:47 AM

Title: [SOLVED] Wrapper Segfault
Post by: mdblabs on October 11, 2017, 12:13:47 AM
Hi,
first of all, I would like to thank you for this great open source project, and community!

I'm trying to create an stand-alone version of solarus, wrapping the execution of the quest, just as the editor code does. I have satisfactory compiled solarus library, and I have created a simple scaffolding C++ code to wrap the execution.

Basically, it mimics solarus-editor's "play" functionality, or solarus -run. The idea is to have a stand-alone binary file, which runs the MainLoop. This is just a test, to understand correctly how solarus works.

Here is my basic main:


int main()
{
std::vector<std::string> arguments = {"","./quest"};
std::vector<char*> argv;

for (const auto& arg : arguments)
    argv.push_back((char*)arg.data());
argv.push_back(nullptr);

const Arguments args(argv.size() - 1, argv.data());   
MainLoop(args).run();

return 0;
}


My quest folder is on same level as binary file. I am using solarus trunk library version (1.6.0), which I compiled without any issue.

Also, if I open my quest with solarus editor, editor runs it without any problem (it's just a basic, clean, quest).

When I run my binary looks like it detects the quest, but I obtain a segfault when it tries to open it.

Here is my output:

./solarus
[Solarus] [0] Info: Solarus 1.6.0
[Solarus] [0] Info: Opening quest './quest'
Segmentation fault: 11


I'm running everything on MacOS and compiled with g++.

Thank you very much for your help.

Best,
mdb
Title: Re: Wrapper Segfault
Post by: Christopho on October 11, 2017, 09:54:43 AM
When you do argv.push_back(nullptr), there is a good chance that your arguments vector gets reallocated so the arg.data() pointers are no longer valid.
Title: Re: Wrapper Segfault
Post by: mdblabs on October 11, 2017, 03:38:28 PM
Thanks Christopho,

yes, you are right: when I add a nullptr to the end, pointers realocated to the end of the array, which seems is ok.

If I don't add the nullptr, args. parsing fails (doesn't locate quest path). Some traces:


std::vector<std::string> arguments = {"","./quest"};
std::vector<char*> argv;

for (const auto& arg : arguments)
    argv.push_back((char*)arg.data());

cout << argv.data() << endl;
argv.push_back(nullptr);
cout << argv.data() << endl;

cout << argv[0] << endl;
cout << argv[1] << endl;

const Arguments args(argv.size() - 1, argv.data());   
MainLoop(args).run();


And the output is:


0x7fd09340e2a0
0x7fd093412b90

./quest
[Solarus] [0] Info: Solarus 1.6.0
[Solarus] [0] Info: Opening quest './quest'
Segmentation fault: 11


If I comment "argv.push_back(nullptr);" line, I get:


0x7fe0b650b560
0x7fe0b650b560

./quest
[Solarus] [0] Info: Solarus 1.6.0
[Solarus] [0] Info: Opening quest '.'                        <---- ??
[Solarus] [0] Error: No quest was found in the directory '.' <---- ??


We need the nullptr to determine end of argv. Without it, it cannot find path to quest. Is this assumption right?

If so, where is the segfault?

Title: Re: Wrapper Segfault
Post by: Christopho on October 11, 2017, 05:52:27 PM
Just create an empty Argument object and then use add_argument to add them. You don't have to mess with char* pointers.
Title: Re: Wrapper Segfault
Post by: mdblabs on October 12, 2017, 10:29:38 AM
I think issue is somewhere else... Route is detected fine, just as with char pointers, but still getting segfault.


Arguments args;
string quest_path("./quest");
cout << quest_path << endl;
args.add_argument(quest_path); 
MainLoop(args).run();

return 0;


Output:

./quest
[Solarus] [0] Info: Solarus 1.6.0
[Solarus] [0] Info: Opening quest './quest'
Segmentation fault: 11


I will review how quests are loaded.
Title: Re: Wrapper Segfault
Post by: Christopho on October 12, 2017, 10:44:09 AM
Can you run a debugger to get a backtrace and know more about the crash?
Title: Re: Wrapper Segfault
Post by: mdblabs on October 12, 2017, 11:09:01 AM
Oooook. Found the issue! Thank you very much for the support.

When running lldb, I get:

Process 20088 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x24)
    frame #0: 0x00007fff04c4d103 libluajit-5.1.2.dylib`___lldb_unnamed_symbol112$$libluajit-5.1.2.dylib + 20
libluajit-5.1.2.dylib`___lldb_unnamed_symbol112$$libluajit-5.1.2.dylib:
->  0x7fff04c4d103 <+20>: movl   0x24(%rbp), %r15d
    0x7fff04c4d107 <+24>: subl   0x18(%rbp), %r15d
    0x7fff04c4d10b <+28>: movl   $0x0, 0x14(%rsp)
    0x7fff04c4d113 <+36>: movl   %r15d, 0x10(%rsp)


So, I found this thread:
https://github.com/pllua/pllua/issues/18 (https://github.com/pllua/pllua/issues/18)

Adding "-pagezero_size 10000 -image_base 100000000" to my LDFLAGS solve the issue.

Thank you very much for your support!

Best,
mdb
Title: Re: [SOLVED] Wrapper Segfault
Post by: vlag on October 13, 2017, 10:15:48 AM
Sorry I'm late :)

Yes this ldflag is needed when you build a 64bit application against LuaJIT on OSX, it is described on the official installation page (http://luajit.org/install.html).
However I handle this flag in the OSX-related cmake file (https://github.com/solarus-games/solarus/blob/dev/cmake/apple/OSXBuild.cmake), could you just tell me how you've built the engine to check if this is a bug or not ?


Best regards.
Title: Re: [SOLVED] Wrapper Segfault
Post by: mdblabs on October 13, 2017, 06:40:07 PM
Thank you very much vlag.

I have attached screenshots of my cmake configuration. Lua Jit + OSX_64.


Title: Re: [SOLVED] Wrapper Segfault
Post by: mdblabs on October 13, 2017, 07:25:04 PM
But, I think is not and issue of Solarus code, but mine. I just create an example, compiled agains Solarus lib, with my own Makefile.

If I run solarus-run from original branch, it runs the quest without any issue.

So, I think, is not a solarus engine bug, but my code.