picodata / tarantool-module

Tarantool Rust SDK
https://docs.rs/tarantool/
BSD 2-Clause "Simplified" License
62 stars 14 forks source link

error loading module 'override.fiber'; luaopen_override_fiber: symbol not found #22

Closed rayman1104 closed 1 year ago

rayman1104 commented 1 year ago

It seems to be a regression after Tarantool 2.11.0. There is next error (but no such error with 2.10.7):

   • Running `cartridge.pre-build`
   • Running `tarantoolctl rocks make`
PANIC: unprotected error in call to Lua API (builtin/internal.loaders.lua:222: error loading module 'override.fiber' from file '/lib/libcarbonite.so':
 /lib/libcarbonite.so: undefined symbol: luaopen_override_fiber)

I've checked it with several tarantool-module versions (0.6.4, 1.1.0), it's same behavior for both of them. We have a basic cartridge app and libcarbonite is our only module, built using tarantool-module as a dependency. Here is the rockspec:

package = 'flare'
version = 'scm-1'
source  = {
    url = '/dev/null',
}
dependencies = {
    'tarantool',
    'lua >= 5.1',
    'checks == 3.1.0-1',
    'cartridge == 2.7.4-1',
    'metrics == 0.13.0-1',
    'migrations == 0.4.2-1',
    'moonwalker',
    'cartridge-cli-extensions == 1.1.1-1',
    'expirationd == 1.4.0-1',
}
build = {
    type = 'none';
}

Also see output for nm libcarbonite.dylib here.

gmoshkin commented 1 year ago

nm.txt file you provided doesn't contain a luaopen_override_fiber function, are you sure it's defined and marked #[no_mangle]?

It would be very helpful if you can try providing a minimized example of your problem.

Update:

luaopen_override_fiber is not supposed to be defined

gmoshkin commented 1 year ago

Do you have any idea, why tarantool would talk about the library with the .so extension, while you're talking about it with .dylib?

rayman1104 commented 1 year ago

yeah, I was testing it both on linux machine and on my M1, the behavior is the same. Do you need nm output for .so file?

gmoshkin commented 1 year ago

yeah, I was testing it both on linux machine and on my M1, the behavior is the same. Do you need nm output for .so file?

A minimized reproduction would help greatly in our ability to help

rayman1104 commented 1 year ago

Sure, here we go: https://github.com/rayman1104/pico-cartridge-repro

gmoshkin commented 1 year ago

Sure, here we go: https://github.com/rayman1104/pico-cartridge-repro

I tried this example on tarantool-2.11 on linux and macos, although on macos I didn't go through cartridge (couldn't install it). I didn't get this error.

It looks to me that the source of you problem is in tarantool or cartridge, not tarantool-module. You can verify if this is true by trying to use a native stored procedure defined in another language, for example C. Here's a simple example:

#include <stdio.h>
int hello() {
    printf("hello from c\n");
    return 0;
}

Compile this with cc -shared -o libcmodule.dylib lib.c where lib.c is the above file. Then setup the LUA_CPATH and try calling the cmodule.hello stored procedure from tarantool.

If you still get that error with this simple C example, then tarantool-module is definitely not the problem

rayman1104 commented 1 year ago

Right, yeah, it's reproduced for C module, then it must be a problem in tarantool or cartridge, I'll report to them. Thanks for the help!

rayman1104 commented 1 year ago

@gmoshkin can you please check my repro once again: https://github.com/rayman1104/lua-cpath-cartridge-repro.git

Guys from Tarantool suggested not to use LUA_CPATH paths without question mark, but it helped only for C module for some reason.

rayman1104 commented 1 year ago

my bad, I also had old env var set in the console and it was affecting cartridge start. now all works!

ramil-bitrise commented 1 year ago

Sorry, I have one more question. Not sure if it's worth to create new issue for that. Now it works in the small repro app, that's good. But in our main app it now fails to load the stored procedures into lua. Previously we could do it as simple as:

box.schema.func.create('attach_carbonite', {language = 'C', if_not_exists = true})
box.func['attach_carbonite']:call()

Now it says that module not found. I tried to replace 'attach_carbonite' -> 'carbonite.attach_carbonite' but it shows the same error: Failed to dynamically load module 'carbonite': module not found.

Do you have any clue, how the module name is determined for the loaded C/rust module? Or how can I look at what modules were added via LUA_CPATH?

gmoshkin commented 1 year ago

@ramil-bitrise in this tutorial it's possible to find an explanation https://www.tarantool.io/en/doc/1.10/tutorials/c_tutorial/#f-c-tutorial-c-stored-procedures

Basically if your stored proc is named mymodule.foo, tarantool will look for module named mymodule and function named foo inside it. If your proc is called just foo it's equivalent to foo.foo, so module name is implicitly foo.

From source code investigation you can find out that tarantool is using the package.search(module) lua function to find your module. You can play around with this function to deduce the following:

  1. First it looks in the current directory for the file named <module-name>.so (or .dylib on mac i guess)
  2. It also looks through the locations in LUA_CPATH environment variable, where it substitutes ? with the module's name

It may or may not be looking somewhere else, I'm not sure

gmoshkin commented 1 year ago

So if naming stored procedure carbonite.attach_carbonite doesn't work, but libcarbonite.attach_carbonite does, it's probably because tarantool is finding it via the 1st method from the comment above, i.e. in the current working directory using the <module-name>.so pattern (note how it doesn't prepend the lib prefix).

Or maybe your LUA_CPATH variable has this pattern path/to/?.so instead of path/to/lib?.so.

I acknowledge that it's confusing that tarantool doesn't add the lib prefix by default when searching for the library in the current working directory

ramil-bitrise commented 1 year ago

Yeah, we couldn't make it with the 2nd method and empirically found a workaround which is the 1st method (making symlink in the current dir that points to the binary) and calling libcarbonite module instead of carbonite. Idk why it didn't work at all with LUA_CPATH, the path was correct but looks like it couldn't find the binary. My rough assumption is that could be because the binary was up a level from the current dir, I'll check later if that's the case.

Thanks for the explanation anyways, it's helpful!