Frequently asked questions ========================== Developing blocks ----------------- How to use C++ for blocks ~~~~~~~~~~~~~~~~~~~~~~~~~ Checkout the example ``std_blocks/cppdemo``. .. note:: *designated initializers*, which are used to initialize ``ubx_proto_`` structures are only supported by g++ versions 8 and newer! What the difference between block types and instances? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There are very few differences. A prototype block is added by module init functions using ``ubx_block_register`` and must also be removed by the corresponding module cleanup hook using ``ubx_block_unregister``. A prototype blocks ``prototype`` ptr is NULL. Block instances are cloned from existing blocks using ``ubx_block_create`` and the instances ``block->prototype`` pointer is set to the block is was cloned from. Normally blocks are cloned from prototype blocks, but it is possible to clone any block (a warning is issued currently). That said, the above are *internals* and you should not rely on them. Instead, use the predicates ``blk_is_proto`` and ``blk_is_instance`` if you need to determine what is what. Why do you cache port pointers in the block info structure? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For two reasons: - it's simpler to cache it once and then just use the pointer directly - to a lesser degree: for performance. It avoids a repeated hash table lookups in ``step``. Note that the ``ubx-genblock`` script automatically takes care caching ports of this. Avoiding ``static`` ~~~~~~~~~~~~~~~~~~~ You can avoid cluttering block functions and globals with ``static``, by adding ``-fvisibility=hidden`` to ``CFLAGS``. Running microblx ---------------- ``blockXY``.so: cannot open shared object file: No such file or directory ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Often this means that the location of the shared object file is not in the library search path. If you installed to a non-standard location, try adding it to ``LD_LIBRARY_PATH``, e.g. .. code:: sh $ export LD_LIBRARY_PATH=/usr/local/lib/ Alternatively run ``sudo ldconfig`` after installing to a standard location such as ``/usr/local/``. luablock: “error object is not a string” ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This typically happens when the ``strict`` module is loaded (directly or indirectly via ``ubx.lua``) in a luablock. It is caused by the C code looking up a non-existing global hook function. Solution: either define all hooks or disable the strict module for the luablock. Running with real-time priorities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To run with realtime priorities, give the luajit binary ``cap_sys_nice`` capabilities, e.g: .. code:: sh $ sudo setcap cap_sys_nice+ep `which luajit` Note that this will grant these capabilities to luajit binary in `PATH`. If you don't want to do this system-wide, you can do this for a local ``luajit`` binary instead. In addition, you should pass the command-line option ``-mlockall`` to ``ubx-launch``, to ensure memory is locked. For scripts, pass the ``ND_MLOCK_ALL`` node attribute to ``ubx_node_init``. I'm not getting core dumps when running with real-time priorities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is not a bug, but a safety mechanism to prevent potential leaking of priviledged data from a ``setcap`` process. To override this, pass the ``ubx-launch`` command-line arg ``-dumpable`` or the for scripts the node attribute ``ND_DUMPABLE``. My script immedately crashes/finishes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This can have several reasons: - You forgot the ``-i`` option to ``luajit``: in that case the script is executed and once completed will immedately exit. The system will be shut down / cleaned up immediately. - You ran the wrong Lua executable (e.g. a standard Lua instead of ``luajit``). If none of this works, see the following topic. Debugging --------- Debugging segfaults ~~~~~~~~~~~~~~~~~~~ One of the best ways to debug crashes is using gdb and the core dump file: .. code:: sh # enable core dumps $ ulimit -c unlimited $ gdb luajit ... (gdb) core-file core ... (gdb) bt Sometimes, running gdb directly on the processes produces better results than post-mortem coredumps. For example, to run the pid example with gdb attached: .. code:: sh $ cd /usr/local/share/ubx/examples/usc/pid $ gdb luajit --args luajit `which ubx-launch` -c pid_test.usc,ptrig_nrt.usc GNU gdb (Debian 9.1-2) 9.1 ... Reading symbols from luajit... (No debugging symbols found in luajit) (gdb) run Starting program: /usr/bin/luajit /usr/local/bin/ubx-launch -c pid_test.usc,ptrig_nrt.usc [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". merging ptrig_nrt.usc into pid_test.usc core_prefix: /usr/local prefixes: /usr, /usr/local [New Thread 0x7ffff7871700 (LWP 2831757)] ... Running valgrind ~~~~~~~~~~~~~~~~ Valgrind is very useful to track down memory leaks or sporadic segfaults. To run it on dynamically loaded modules, the ``UBX_CONFIG_VALGRIND`` flag must be enabled in ``ubx.h``. This flag will pass the ``RTLD_NODELETE`` flag to ``dlopen(3)``, which causes modules not really to be unloaded. This is essential for valgrind to print meaningful traces in module code. After that, you can run valgrind as follows on an `usc` file: .. code:: sh valgrind --leak-check=full \ --track-origins=yes \ luajit `which ubx-launch` -t 3 -c examples/usc/threshold.usc ... This will run the demo for 3 seconds and then exit. Valgrind may print warnings related to luajit like ``Conditional jump or move depends on uninitialised value``, which can be ignored (or silenced by building luajit with valgrind support , see ``-DLUAJIT_USE_VALGRIND``) Running a script can be done likewise: .. code:: sh $ valgrind --leak-check=full \ --track-origins=yes \ luajit tests/test_ptrig.lua ... meta-microblx ------------- building luajit fails ~~~~~~~~~~~~~~~~~~~~~ If cross-compiling luajit fails with ``fatal error: asm/errno.h: No such file or directory``, install ``gcc-multilib`` on the build host.