All right, so far, the forwarding of sessions works. However, when closing a session, there is an issue.
Whenever a client connection is closed, the client calls close() with a session cap on the root. The root then has to look into its open sessions, and compare the session caps of each of those open sessions with the provided cap, and then further cleans up all data related to that session.
For the service router example, it does the following on line 52 (service_router/main.cc):
for (Forwarded_capability *cap = _caps.first(); cap; cap = cap->next()) { if (*cap == session) return cap; }
it checks if these capabilities are equal using the '==' operator. In Capability, this operator compares the internal pointers Native_capability::Data *_data of each Capability object, which points to an object containing metadata such as a Rpc destination and a key.
However, when this session capability is passed as argument to the close() or upgrade() method of the root RPC interface, the unmarshaller at the server side will always create a new Capability object with new data using the Capability_space_tpl::import method (If I am not mistaken), instead of using lookup(). This is done for instance on linux and on nova in ipc.cc. Therefore the cap pointers will never be equal although they point to different duplicate cap data objects with the same content. Is this the correct behaviour?
When testing it with print() by inserting the following line
log("testing... session = ", session, " cap = ", cap, " equal = ", session == cap);
it outputs the following:
session = cap<socket=27,key=474> cap = cap<socket=27,key=474> equal = 0
So the comparison will always fail, and the overloaded close() and upgrade() methods of Root cannot close/upgrade the correct session.
Am I missing something here or is it not possible right now to locally keep track of multiple forwarded session capabilities in this way?
Or is there a workaround?
Regards,
Boris
On 30-01-17 11:09, Norman Feske wrote:
Hi Boris,
You just missed a tiny piece of the puzzle: The 'Slave::Connection' does not only provide the session interface of the slave's service but also the corresponding 'Session_capability' (it inherits 'CONNECTION::Client', so the 'Slave::Connection' _is_ a session capability). Instead of calling the 'File_system' methods, the media component would pass this 'Session_capability' to init as response to the 'File_system' session request that originated from init.
I assume here the session() method inherited from Genode::Root has to be implemented such that it returns the capability that is the Slave::Connection after that connection has been initiated?
yes.
Cheers Norman