Although we tried to avoid it, there might still be shell scripts where we use ‘+=’, 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:
cc1plus: warnings being treated as errors
parser/ugrammar.hh: In member function \
‘void yy::parser::yypush_(const char*, int, yy::parser::symbol_type&)’:
parser/ugrammar.hh:1240: error: ‘<anonymous>’ is used uninitialized \
in this function
parser/ugrammar.cc:1305: note: ‘<anonymous>’ was declared here
parser/ugrammar.hh: In member function \
‘void yy::parser::yypush_(const char*, yy::parser::stack_symbol_type&)’:
parser/ugrammar.hh:1240: error: ‘<anonymous>’ is used uninitialized \
in this function
parser/ugrammar.cc:1475: note: ‘<anonymous>’ was declared here
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:
configure:12176: error: possibly undefined macro: AM_LANGINFO_CODESET
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
configure:12246: error: possibly undefined macro: gl_GLIBC21
it probably means your Automake installation is incomplete. See the Automake item in Section 18.1.
If you experience the following failure:
checking if java works...
configure: error: The Java VM java failed
(see config.log, check the CLASSPATH?)
and if you looked at ‘config.log’, you should find something like:
Exception in thread "main" java.lang.NoClassDefFoundError: Test
Caused by: java.lang.ClassNotFoundException: Test
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Could not find the main class: Test. Program will exit.
You might be trying to compile Urbi SDK from a directory with non-ASCII characters in its full name (for instance ‘/home/jessy/Téléchargements/Sources’). In that case the JVM fails to decode properly the path, and configure fails with the above message.
Move you sources elsewhere, with only plain ASCII characters, such as ‘/home/jessy/Sources’.
Be sure to read Section 18.3. In particular, run ‘make check’ several times (see Section 18.3 to know why). If the failures remain, please submit the ‘test-suite.log’ file(s) (see Section 14.5.3).
If you experience the following failure on Mac OS X:
$ urbi-launch-java --port-file server.port tests/all/All.jar
Error occurred during initialization of VM
Unable to load native library: libjava.jnilib
then you have something in the DYLD_LIBRARY_PATH that annoys the Java VM. Although we have not pinpointed it exactly, it seems to be a problem in our libjpeg: first run ‘make -C sdk-remote/jpeg clean’ then ‘make -S sdk-remote/jpeg’.
If on GNU/Linux you get an error such as:
urbi-sdk/2.7.1 $ ./bin/urbi
./bin/urbi: error while loading shared libraries: libport.so: \
cannot open shared object file: No such file or directory
then check that ‘/proc’ is properly mounted. To make Urbi SDK relocatable, executables and libraries use a relative path to their peers. To resolve these paths into absolute paths, the loader needs to know where the program is located, a feature provided by ‘/proc’. If for instance you run Urbi SDK in a chrooted environment, then it is possible that you forgot to mount ‘/proc’. The traditional ps utility also needs ‘/proc’ to be mounted, so running it would also help checking if the setup is complete.
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 14.2.3.
Your program might be deeply recursive, or use large temporary objects. Use ‘--stack-size’ to augment the stack size, see Section 19.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.
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.
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
$
If you are running Cygwin, then have a look at the following section, which uses some of its tools.
A specific constraint, for which currently we do not have nice solutions, is that when Windows loads a DLL, it looks for all its dependencies (i.e., other DLL that are needed) in the directory from which the program was run, or in the PATH. There is no way, that we are aware of, to embed in a DLL the information about where the dependencies are. When trying to load a DLL with missing dependencies, say ‘foo.dll’, the error message will be something like “can’t open the module”, and worse yet, if you read the detailed log messages (by setting GD_LEVEL to DUMP for instance) it will report “failed with error 126: The specified module could not be found” although the file is there.
So first try to understand what are the missing dependencies. Under Windows, use DependencyWalker (see http://dependencywalker.com) to check that a given DLL finds all its dependencies. If some dependencies are not found either:
The first approach is more tractable. Beware that dependencies may also have dependencies…
Cygwin Use the cygcheck.exe program to check dependencies. Beware that you must provide a qualified path to the file. Chances are that if
does not work and will pretend that ‘foo.dll’ does not exist (although it’s right there), then this will work:
In this output, look for lines like these:
cygcheck: track_down: could not find OgreMain.dll
cygcheck: track_down: could not find OIS.dll
cygcheck: track_down: could not find libuobject-vc90.dll
and make sure that ‘OgreMain.dll’, ‘OIS.dll’ and so forth are visible in the PATH (don’t be worry about ‘libuobject-vc90.dll’, urbi-launch will take care of it). Note that when they are finally visible from the PATH, then you can run
without having to specify the path.
In practice, users who want to “delete an object” actually want to remove a slot — see Section 4.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;
[00000002] 42
function get()
{
echo(mind);
}|;
get();
[00000003] *** 42
function Object.get()
{
echo(mind)
}|;
// Where is my mind?
Object.get();
[00000004:error] !!! lookup failed: mind
[00000004:error] !!! called from: get
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
On the other hand, local variables are not stored in an object, but in the execution stack: their lifetime spans from their declaration point to the end of the current scope. They are declared with the ‘var’ keyword.
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 (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
Step by step:
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
[00000000:error] !!! called from: getHis
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);
}|;
In the previous example, typing global will look for the global slot in this. Since this necessarily inherits Object, it will necessarily be found.
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 always accessible no matter where you are. 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
package lang.Constants
{
var Pi = 3.14;
var Euler = 2.17;
var One = 1;
// ...
}|;
// Test it.
Constants.Pi;
[00000000] 3.14
function Object.testPi() { echo(Constants.Pi) }|;
42.testPi();
[00000000] *** 3.14
import Constants.*;
Pi;
[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);
The init function of parent classes is not called automatically when calling new on ba child classe. It is the responsibility of the child to invoke init itself, using Code.apply:
package MyModule
{
class Parent
{
function init(x)
{
var this.x = x;
};
};
class Child: Parent
{
function init(x, y)
{
Parent.init.apply([this, x]);
var this.y = y;
}
};
};
import MyModule;
var c = MyModule.Child.new(1, 2);
[00028287] Child_0xb48e0e48
c.x;
[00029646] 1
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 10.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.
See Listing 11, 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.
See Section 21.15.5.
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.
Use the for construct (Listing 20.7.6), or the List.each method:
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 Listing 30.
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 https://github.com/jcbaillie/urbi/urbi/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, specify the Urbi version you are using (run ‘urbi --version’) and whether this bug is blocking you or not. Please keep kernel-bugs@lists.gostai.com in copy of all your correspondence: 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 18.3.