At random places we use ‘+=’ in /bin/sh scripts, which Ash (aka, dash and sash) does not support. Please, use bash or zsh instead of Ash as /bin/sh.
If you encounter this error:
then you found a problem that we don’t know how to resolved currently. Downgrade from GCC-4.4 to GCC-4.3.
If at bootstrap you have something like:
it probably means your Automake installation is incomplete. See the Automake item in Section 17.1.
Be sure to read Section 17.9. In particular, run ‘make check’ several times (see Section 17.9 to know why). If the failures remain, please submit the ‘test-suite.log’ file(s) (see Section 15.5.3).
This error is raised when you try to install a program like vcredist-x86.exe. This program use the “Windows Installer” which is probably outdated on your system.
To fix this problem, update the “Windows Installer” and re-start the installation of vcredist which should no longer fail.
This library is necessary to start running any application. Run ‘vcredist-x86.exe’ to install the missing libraries.
If you have used the Urbi SDK installer, it is ‘vcredist-x86.exe’ in your install directory. Otherwise download it from the Microsoft web site. Be sure to get the one corresponding to the right Visual C ++ version.
Same answer as Section 15.2.2.
Your program might be deeply recursive, or use large temporary objects. Use ‘--stack-size’ to augment the stack size, see Section 18.3.
Note that one stack is allocated per “light thread”. This can explain why programs that heavily rely on concurrency might succeed where sequential programs can fail. For instance the following program is very likely to quickly exhaust the (single) stack.
But if you use & instead of |, then each recursive call to consume will be spawn with a fresh stack, and therefore none will run out of stack space:
However your machine will run out of resources: this heavily concurrent program aims at creating no less than 2513 threads, about 2.68 × 10156 (a 156-digit long number, by far larger than the number of atoms in the observable universe, estimated to 1080).
If urbi-launch (or urbi) fails to load an UObject (a shared library or DLL) although the file exists, then the most probable cause is an undefined symbol in your shared library.
Getting a better diagnostic First, set the GD_LEVEL environment variable (see Section 18.1.2) to some high level, say DUMP, to log messages from urbi-launch. You might notice that your library is not exactly where you thought urbi-launch was looking at.
GNU/Linux A libltdl quirk prevents us from displaying a more accurate error message. You can use a tool named ltrace to obtain the exact error message. Ltrace is a standard package on most Linux distributions. Run it with ‘ltrace -C -s 1024 urbi-launch ...’, and look for lines containing ‘dlerror’ in the output. One will contain the exact message that occurred while trying to load your shared library. It is also useful to use ldd to check that the dependencies of your object are correct. See the documentation of ldd on your machine (‘man ldd’). The following run is successful: every request (left-hand side of =>) is satisfied (by the file shown on the right-hand side).
$ all.so
linux-gate.so.1 => (0xb7fe8000)
libstdc++.so.6 => \
/usr/lib/gcc/i686-pc-linux-gnu/4.4.1/libstdc++.so.6 (0xb7eba000)
libm.so.6 => /lib/libm.so.6 (0xb7e94000)
libc.so.6 => /lib/libc.so.6 (0xb7d51000)
libgcc_s.so.1 => \
/usr/lib/gcc/i686-pc-linux-gnu/4.4.1/libgcc_s.so.1 (0xb7d35000)
/lib/ld-linux.so.2 (0xb7fe9000)
The following run shows a broken dependency.
# A simple C++ program.
$ echo’int main() {}’>foo.cc
# Compile it, and depend on the libport shared library.
$ g++ foo.cc -Lurbi-root/gostai/lib -lport -o foo
# Run it.
$ ./foo
./foo: error while loading shared libraries: \
libport.so: cannot open shared object file: No such file or directory
# See that ldd is unhappy.
$ ldd foo
linux-gate.so.1 => (0xb7fa4000)
libport.so => not found
libstdc++.so.6 => \
/usr/lib/gcc/i686-pc-linux-gnu/4.4.1/libstdc++.so.6 (0xb7eae000)
libm.so.6 => /lib/libm.so.6 (0xb7e88000)
libgcc_s.so.1 => \
/usr/lib/gcc/i686-pc-linux-gnu/4.4.1/libgcc_s.so.1 (0xb7e6c000)
libc.so.6 => /lib/libc.so.6 (0xb7d29000)
/lib/ld-linux.so.2 (0xb7fa5000)
Notice the ‘not found’ message. The shared object could not be loaded because it is not found in the runtime path, which is the list of directories where the system looks for shared objects to be loaded when running a program.
You may extend your LD_LIBRARY_PATH to include the missing directory.
Mac OS X Set the DYLD_PRINT_LIBRARIES environment variable to 1 to make the shared library loader report the libraries it loads on the standard error stream. Use otool to check whether a shared object “finds” all its dependencies.
$ otool -L all.so
all.so:
/usr/lib/libstdc++.6.dylib \
(compatibility version 7.0.0, current version 7.4.0)
/usr/lib/libgcc_s.1.dylib \
(compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib \
(compatibility version 1.0.0, current version 111.1.4)
The following run shows a broken dependency.
# A simple C++ program.
$ echo’int main() {}’>foo.cc
# Compile it, and depend on the libport shared library.
$ g++ foo.cc -Lurbi-root/gostai/lib -lport -o foo
# Run it.
$ ./foo
dyld: Library not loaded: @loader_path/libport.dylib
Referenced from: /private/tmp/./foo
Reason: image not found
# See that otool is unhappy.
$ otool -L ./foo
./foo:
@loader_path/libport.dylib \
(compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libstdc++.6.dylib \
(compatibility version 7.0.0, current version 7.4.0)
/usr/lib/libgcc_s.1.dylib \
(compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib \
(compatibility version 1.0.0, current version 111.1.5)
The fact that the ‘libport.dylib’ was not found shows by the unresolved relative runtime-path: ‘@loader_path’ still shows. Use DYLD_LIBRARY_PATH to specify additional directories where the system should look for runtime dependencies.
$ DYLD_PRINT_LIBRARIES=1 \
DYLD_LIBRARY_PATH=urbi-root/lib:$DYLD_LIBRARY_PATH \
./foo
dyld: loaded: /private/tmp/./foo
dyld: loaded:urbi-root/lib/libport.dylib
dyld: loaded: /usr/lib/libstdc++.6.dylib
dyld: loaded: /usr/lib/libgcc_s.1.dylib
dyld: loaded: /usr/lib/libSystem.B.dylib
dyld: loaded:urbi-root/lib/libboost_filesystem-mt.dylib
dyld: loaded:urbi-root/lib/libboost_signals-mt.dylib
dyld: loaded:urbi-root/lib/libboost_system-mt.dylib
dyld: loaded:urbi-root/lib/libboost_thread-mt.dylib
dyld: loaded: /usr/lib/system/libmathCommon.A.dylib
$
Windows In plain native Windows, use DependencyWalker (see http://dependencywalker.com) to check that a given DLL finds all its dependencies.
Alternatively, under Cygwin, you can use the cygcheck.exe program to check dependencies.
If you need to add a DLL that was missing, put it somewhere in the PATH, or in the current working directory.
In practice, users who want to “delete an object” actually want to remove a slot — see Section 6.1. Users who want to clear an object can empty it — see Section 16.2.
Note that myObject = nil does not explicitly destroy the object bound to the name myObject, yet it may do so provided that myObject was the last and only reference to this object.
One frequently asked question is what visibility do variables have in urbiscript, especially when they are declared at the top-level interactive loop. In this section, we will see the mechanisms behind slots, local variables and scoping to fully explain this behavior and determine how to proceed to give the right visibility to variables.
For instance, this code might seem confusing at first:
var mind = 42;[00000001] 42
function get()
{
echo(mind);
}|;
get();[00000000] *** 42
function Object.get()
{
echo(mind)
}|;// Where is my mind?
Object.get;[00000000:error] !!! lookup failed: mind
Local variables, slots and targets The first point is to understand the difference between local variables and slots. Slots are simply object fields: a name in an object referring to another object, like members in C ++. They can be defined with the setSlot method, or with the var keyword.
// Add an ‘x’ slot in Object, with value 51.
Object.setSlot("x", 51);[00000000] 51// This is an equivalent version, for the ‘y’ slot.
var Object.y = 51;[00000000] 51
// We can access these slots with the dot operator.
Object.x + Object.y;[00000000] 102
function foo()
{
// Declare an ‘x’ local variable, with value 51.
var x = 51;
// ‘x’ isn’t stored in any object. It’s simply
// available until the end of the scope.
echo(x);
}|;
You probably noticed that in the last two code snippets, we used the var keyword to declare both a slot in Object and a local variable. The rule is simple: var declares a slot if an owning object is specified with the dot notation, as in var owner.slot, and a local variable if only an unqualified name is given, as in var name.
{
// Store a ‘kyle’ slot in Object.
var Object.kyle = 42;
// Declare a local variable, limited to this scope.
var kenny = 42;
};// End of scope.[00000000] 42
// Kyle survived.
echo(Object.kyle);[00000000] *** 42
// Oh my God, they killed Kenny.
echo(kenny);[00000000:error] !!! lookup failed: kenny
There is however an exception to this rule: do and class scopes are designed to define a target where to store slots. Thus, in do and class scopes, even unqualified var uses declare slots in the target.
// Classical scope.
{
var arm = 64;// Local to the scope.
};[00000000] 64
// Do scope, with target Object
do (Object)
{
var chocolate = 64;// Stored as a slot in Object.
};[00000000] Object
// No arm...
echo(arm);[00000000:error] !!! lookup failed: arm// ... but still chocolate!
echo(chocolate);[00000000] *** 64
Last tricky rule you must keep in mind: the top level of your connection — your interactive session — is a do (lobby) scope. That is, when you type var x directly in your connection, it stores an x slot in the lobby object. So, what is this lobby? It’s precisely the object designed to store your top-level variables. Every Urbi server has an unique Lobby (??sec:std-Lobby) (note the capital), and every connection has its lobby that inherits the Lobby. Thus, variables stored in Lobby are accessible from any connection, while variables stored in a connection’s lobby are local to this connection.
To fully understand how lobbies and the top-level work, we must understand how calls — message passing — work in urbiscript. In urbiscript, every call has a target. For instance, in Object.x, Object is the target of the x call. If no target is specified, as in x alone, the target defaults to this, yielding this.x. Knowing this rules, plus the fact that at the top-level this is lobby, we can understand better what happens when defining and accessing variables at the top-level:
// Since we are at the top-level, this stores x in the lobby.// It is equivalent to ‘var lobby.x’.
var x ="hello";[00000000] "hello"
// This is an unqualified call, and is thus// equivalent to ‘this.x’.// That is, ‘lobby.x’ would be equivalent.
x;[00000000] "hello"
Solving the tricky example We now know all the scoping rules required to explain the behavior of the first code snippet. First, let’s determine why the first access to mind works:
// This is equivalent to ‘var lobby.myMind = 42’.
var myMind = 42;[00000001] 42// This is equivalent to ‘function lobby.getMine...’
function getMine()
{
// This is equivalent to ‘echo(this.myMind)’
echo(myMind);
}|;// This is equivalent to ‘this.getMine()’, i.e. ‘lobby.getMine()’.
getMine();[00000000] *** 42
We can also explain why the second test fails:
// Create the ‘hisMind’ slot in the lobby.
var hisMind = 42;[00000000] 42// Define a ‘getHis’ method in ‘Object’.
function Object.getHis()
{
// Equivalent to echo(this.hisMind).
echo(hisMind)
}|;// Call Object’s getHis method.
Object.getHis;[00000000:error] !!! lookup failed: hisMind
Step by step:
In the method, this is Object. Thus hisMind, which is this.hisMind, fails because Object has no such slot.
The key to understanding this behavior is that any unqualified call — unless it refers to a local variable — is destined to this. Thus, variables stored in the lobby are only accessible from the top-level, or from functions that are targeted on the lobby.
So, where to store global variables? From these rules, we can deduce a simple statement: since unqualified slots are searched in this, for a slot to be global, it must always be accessible through this. One way to achieve this is to store the slot in Object, the ancestor of any object:
var Object.global = 1664;[00000000] 1664
function any_object()
{
// This is equivalent to echo(this.global)
echo(global);
}|;
This solution would work; however, storing all global variables in Object wouldn’t be very clean. Object is rather designed to hold methods shared by all objects. Instead, a Global object exists. This object is a prototype of Object, so all his slots are accessible from Object, and thus from anywhere. So, creating a genuine global variable is as simple as storing it in Global:
Note that you might want to reproduce the Global system and create your own object to store your related variables in a more tidy fashion. This is for instance what is done for mathematical constants:
// Store all constants here
class Constants
{
var Pi = 3.14;
var Euler = 2.17;
var One = 1;
// ...
}|;// Make them global by making them accessible from Global.
Global.addProto(Constants);[00000000] Global
// Test it.
Global.Pi;[00000000] 3.14
Pi;[00000000] 3.14
function Object.testPi() { echo(Pi) }|;
42.testPi;[00000000] *** 3.14
var O2 = Object.new |// Syntax...
var O2.mySlot1 = 42;[00000001] 42
// and semantics.
O2.setSlot("mySlot2", 23);[00000001] 23
Note that in a method, this designates the current object. It is needed to distinguish the name of a slot in the current object, versus a local variable name:
{
// Create a new slot in the current object.
var this.bar = 42;
// Create a local variable, which will not be known anymore
// after we exit the current scope.
var qux = 23;
}|
qux;[00000001:error] !!! lookup failed: qux
bar;[00000001] 42
class O
{
var mySlot = 42;
}|// Sugarful.
O.mySlot = 51;[00000001] 51
// Sugar-free.
O.updateSlot("mySlot", 23);[00000001] 23
// In two steps: definition, and initial assignment.
var myLocalVariable;
myLocalVariable ="foo";[00000001] "foo"// In a single step: definition with an initial value.
var myOtherLocalVariable ="bar";[00000001] "bar"
class myObject
{
function init(x, y)
{
var this.x = x;
var this.y = y;
};
};
myInstance = myObject.new(10, 20);
var myObject = Object.new;
var myObject.myFunction = function (x, y)
{ echo ("myFunction called with "+ x +" and "+ y) };
You can also use the following notation to add a function to your object:
or even group definitions within a do scope, which will automatically define new slots instead of local variables and functions:
or group those two statements by using a convenient class scope:
See Section 11.3, in the urbiscript User Manual, for an introduction about Tags. Then for a definition of the Tag objects (construction, use, slots, etc.), see Tag (??sec:std-Tag).
See Chapter 12, in the urbiscript User Manual, for an introduction about event-based programming. Then for a definition of the Event objects (construction, use, slots, etc.), see Event (??sec:std-Event).
See Section 20.14.3.
The ? marker indicates that we are looking for an event instead of a Boolean condition. The construct var msg indicates that the msg variable will be bound (as a local variable) in the body part of the at construct, with whatever value is present in the event that triggered the at.
We are receiving a lot of questions on thread-safety issues in UObject code. So here comes a quick explanation on how things work in plugin and remote mode, with a focus on those questions.
In plugin mode, all the UObject callbacks (timer, bound functions, notifyChange and notifyAccess targets) are called synchronously in the same thread that executes urbiscript code. All reads and writes to Urbi variables, through UVar, are done synchronously. Access to the UObject API (reading/writing UVars, using call()...) is possible from other threads, though those operations are currently using one serialization lock with the main thread: each UObject API call from an other thread will wait until the main thread is ready to process it.
Execution model In remote mode, a single thread is also used to handle all UObject callbacks, for all the UObjects in the same executable. It means that two bound functions registered from the same executable will never execute in parallel. Consider this sample C ++ function:
int MyObject::test(int delay)
{
static const int callNumber = 0;
int call = ++callNumber;
std::cerr <<"in "<< call <<": "<< time() << std::endl;
sleep(delay);
std::cerr <<"out "<< call <<": "<< time() << std::endl;
return 0;
}
If this function is bound in a remote uobject, the following code:
will produce the following output (assuming the first call to time returns 1000).
However, the execution of the Urbi kernel is not “stuck” while the remote function executes, as the following code demonstrates:
The corresponding output is (mixing the kernel and the remote outputs):
As you can see, Urbi semantics is respected (the execution flow is stuck until the return value from the function is returned), but the kernel is not stuck: other pieces of code are still running.
Thread-safety The liburbi and the UObject API in remote mode are thread safe. All operations can be performed in any thread. As always, care must be taken for all non-atomic operations. For example, the following function is not thread safe:
void
writeToVar(UClient* cl, std::string varName, std::string value)
{
(*cl) << varName <<" = "<< value <<";";
}
Two simultaneous calls to this function from different threads can result in the two messages being mixed. The following implementation of the same function is thread-safe however:
void
writeToVar(UClient* cl, std::string varName, std::string value)
{
std::stringstream s;
s << varName <<" = "<< value <<";";
(*cl) << s.str();
}
since a single call to UClient’s operator << is thread-safe.
See Chapter 24.
You are encouraged to submit patches to kernel@lists.gostai.com, where they will be reviewed by the Urbi team. If they fit the project and satisfy the quality requirements, they will be accepted. As of today there is no public repository for Urbi SDK (there will be, eventually), patches should be made against the latest source tarballs (see http://gostai.com/downloads/urbi-sdk/2.x/).
Even though Urbi SDK is free software (GNU Affero General Public License 3+, see the ‘LICENSE.txt’ file), licensing patches under GNU AGPL3+ does not suffice to support our dual licensed products. This situation is common, see for instance the case of Oracle VM Virtual Box, http://www.virtualbox.org/wiki/Contributor_information.
There are different means to ensure that your contributions to Urbi SDK can be accepted. None require that you “give away your copyright”. What is needed, is the right to use contributions, which can be achieved in two ways:
Bug reports should be sent to kernel-bugs@lists.gostai.com, it will be addressed as fast as possible. Please, be sure to read the FAQ (possibly updated on our web site), and to have checked that no more recent release fixed your issue.
Each bug report should contain a self-contained example, which can be tested by our team. Using self-contained code, i.e., code that does not depend on other code, helps ensuring that we will be able to duplicate the problem and analyze it promptly. It will also help us integrating the code snippet into our non-regression test suite so that the bug does not reappear in the future.
If your report identifies a bug in the Urbi kernel or its dependencies, we will prepare a fix to be integrated in a later release. If the bug takes some time to fix, we may provide you with a workaround so that your developments are not delayed.
In your bug report, make sure that you indicate the Urbi version you are using (use ‘urbi --version’ to check it out) and whether this bug is blocking you or not. Also, please keep kernel-bugs@lists.gostai.com in copy of all your correspondence, and do not reply individually to a member of our team as this may slow down the handling of the report.
If your bug report is about a failing ‘make check’, first be sure to read Section 17.9.