-
-
Notifications
You must be signed in to change notification settings - Fork 605
Porting native applications to OSv
There are two way to run a native (e.g. C/C++) app on OSv:
- Upload and call it on run time
- Create a "precooked" appliance of OSv and the application
Once launching an appliance, it will automatically start both OSv and the application on top of it.
On both cases, the application has to be in a shared library format (.so). More on how to create a share library from an existing application here
Assuming you have a a shared library x.so you want to run. You will need to:
- Upload the library to OSv file system
- Call it
To upload a file to OSv, you can use either:
- REST API
- REST API Dashboard (which use REST API)
To upload a file using REST API:
curl -F filedata=@temp-test-file.txt http://osv-ip:8000/file/{path}/
Where osv-ip is the OSv VM IP. To upload a file using Dashboard, brows to http://osv-ip:8000, click the REST button, and choose POST file/
- [More on OSv REST API](Using OSv REST API)
- A full list of OSv REST API
To Run application, use the POST /app/
REST API.
The easiest way to create an OSv appliance is using Capstan. Go check it out!
We do not yet have full POSIX compatibility, so when running a new application you may encounter symbols that are not yet there. A list of applications that are known to work (as in specifically tested by us) can be found at our osv-apps repository.
The most common issue one will encounter is a missing symbol. This is a real example from the enablement of redis:
Failed looking up symbol __register_atfork
[backtrace]
0x31a7f3 <elf::object::resolve_pltgot(unsigned int)+83>
0x35fbb3 <__elf_resolve_pltgot+47>
0x31c8e5 <elf::program::get_library(std::string, std::vector<std::string, std::allocator<std::string> >)+1317>
0x3b7734 <osv::run(std::string, int, char**, int*)+132>
0x3b7b80 <osv::run(std::string, std::vector<std::string, std::allocator<std::string> >, int*)+576>
0x20d366 <run_main(std::vector<std::string, std::allocator<std::string> > const&)+246>
0x20ef10 <do_main_thread(void*)+1024>
0x3fd6a6 <sync+70>
0x3a246b <thread_main_c+27>
0x360f06 <call_signal_handler_thunk+0>
As we currently don't have fork()
support, all we need to do is provide an empty implementation to keep the program happy. See for instance the following example of how it can be fixed. Of course depending on what function you run into, it does have to be implemented in a proper way.
Some other applications tend to call the system calls directly. It is not common, but it does happen. In those cases, our syscall()
implementation should show you the missing one:
syscall(): unimplemented system call 1. Aborting.
[backtrace]
0x1000000bf2ab <malloc_vcprintf+43>
We can see in this example, that the syscall "1" is missing. That corresponds to the write()
system call.
Here is an example of an implementation.
For most of the system calls, this implementation should be extremely trivial: it is just a matter of passing the right arguments to the corresponding function. Maybe at some point it will be even automatic.
We try to keep implementation of symbols as simple as possible in order to support the applications. For example, if an application just calls into a symbol but is not interested at all in its output, just providing the symbol may be enough (see for instance the register_atfork
in this same document). We tend to move to more significant work in those cases, and mark the function as WARN_STUBBED (See /include/osv/stubbing.hh
)
But for other applications that same usage may not be enough. Those warnings are only visible when OSv is running in verbose mode. Assuming you are running OSv from the standalone command line as explained in our README, you need to add the -V
switch to see those. For example:
[glauber@localhost osv]$ ./scripts/run.py -V
[...]
[I/35 dhcp]: Waiting for IP...
[I/206 dhcp]: Server acknowledged IP for interface eth0
[I/206 dhcp]: Configuring eth0: ip 192.168.122.15 subnet mask 255.255.255.0 gateway 192.168.122.1 MTU 0
pthread_mutexattr_init() stubbed <=== Look here
If a stubbed function is affecting an application or not, is something that requires knowledge of application semantics to decide. But if something is misbehaving, looking at stubbed functions is a great start.