Wiley.Symbian.OS.Internals.Real.time.Kernel.Programming.Dec.2005.eBook-DDU (779891), страница 32
Текст из файла (страница 32)
There would then be a race between the server setting the cookieafter creating the session object and it completing the disconnect request.If the disconnect message is completed first, the kernel-side session objectis no longer valid when the server tries to set the cookie using the connect message and it will be panicked. Otherwise, if the session cookie isset first, then the disconnect message will complete as a no-op, since thecookie within it is null, and a session object is leaked in the server.To avoid either of these situations, we have introduced the CLOSINGstate. If a connect message has been delivered but not yet completedwhen the last user handle to the session is closed, the delivery of thedisconnect message to the server is delayed until the session cookie isupdated to indicate successful creation of a user-side session object.
Ifthe connect message completes without the cookie having been updated,there is no user-side session object to clean up but a disconnect messageis still sent to ensure the lifetime of the session object extends untilthe completion of other messages which may have been sent to theunconnected session. If there is an undelivered connect message, thisis immediately removed from the queue to avoid the possibility of anorphan session object being created.Note that the ability to create process-relative session handles and theasynchronous nature of sending a connect message mean that you cansend other messages to a server both before and after a connect messagehas been sent, and before the connect message has been completed, socare must be taken over this possibility.
However, when a disconnectmessage is sent no more messages may be sent to the session by virtue ofthe fact that it is sent once all user-side handles to the session have beenclosed. Therefore the disconnect message is always the last message to asession that is completed by the server and the session object may be safelydestroyed after completing it, without causing lifetime issues for the server.There are two methods to send synchronous and asynchronous messages – SendSync() and Send() (first overload above), respectively.These validate certain preconditions, select an appropriate message objectto store the new message, and then pass the selected message object tothis method:Send(RMessageK* aMsg, TInt aFunction, const TInt* aPtr,TRequestStatus* aStatus);This method populates the message object, increments the currentthread’s IPC count (DThread::iIpcCount), adds the message to thesession’s queue and delivers it to the server.
If the server has terminated,or is in the process of doing so, sending the message fails immediately.138INTER-THREAD COMMUNICATIONNeither Send() method permits the sending of a disconnect message,since this is sent automatically by DSession::Close() when the lastclient session handle is closed.At the other end of a normal message’s life, it is completed inExecHandler::MessageComplete() (called from RMessagePtr2::Complete()). If the message is a disconnect message, then execution is simply transferred to DSession::CloseFromDisconnect().If not, then what happens next is pretty much the reverse of the send procedure: the message is removed from the session queue, the sending thread’sIPC count is decremented and the client thread’s request is completed. Theonly exception to this is if the session is closing; this happens if the clienthas closed all handles to the session but the disconnect message has notyet been completed by the server.
In this case the client thread’s requestis not completed.Messages can also be completed from DSession::Detach(), whichis called either when the server terminates (that is, when the last referenceto the server is closed in DServer::Close()) or when completing adisconnect message. In this case, the message is again removed from thesession queue, the sending thread’s IPC count decremented and the clientrequest is completed (if the session is not closing).We have just seen that it is possible for a message not to be completed – this happens when the session is closing, as we saw above. Andyet previously I said that guaranteed message completion is one of theproperties of the client-server system.
The explanation here is that theclient having an outstanding message when calling Close() on a sessionis considered to be a client-side programming error. There is clearly a racebetween the server completing such outstanding asynchronous requestsand the disconnect request being processed. Those requests processedafter the session has been closed cannot be completed whereas thosebefore can, so the behavior of client-server has always been undefinedby Symbian in this situation.The actual behavior of EKA2 differs from EKA1 here.
In EKA1, disconnect messages overtake all undelivered messages to the server andthese undelivered messages are discarded. Now, in EKA2, the serverprocesses all delivered messages before processing the disconnect message – although, as we’ve seen, such messages can still not be completedto the client. All this said, we don’t advise you to rely on this new behaviorof EKA2, because we explicitly state this to be a programming error andmay change the behavior of this area in future.One of the other main functions of the session object is to control thesession’s ‘‘sharability’’. With the advent of a fully message-centric design,there is no requirement for the session to hold a handle to the client thread,and providing different levels of accessibility to a session – restricted toone thread, restricted to one process or sharable with any thread – is nowa simple matter of recording the stated intentions of the user-mode serverCLIENT-SERVER ITC139in iSvrSessionType and then creating a handle to the session for anyclient that is allowed access to it, when requested.
That is, whether agiven thread can access a session is now determined purely by whetherit has a handle to the session or not as the access check is performed athandle-creation time.This accounts for the introduction of the new method DObject::RequestUserHandle(). Suppose a server only supports nonsharable sessions. Then a user-mode thread with a handle to a sessioncould just duplicate that handle, making a process-relative handle, andover-ride the settings of the server. But DSession ’s over-ridden RequestUserHandle() checks the value in iSvrSessionType to see whetherthe requested sharing level is allowed by the server, and thereby enforcesthe user-mode server’s requested policy on session sharing.To maintain backwards compatibility, the user-side APIs for creating sessions default to creating a session that is ‘‘unshareable’’, evenif shared sessions are supported by the server.
This ‘‘current sharabilitylevel’’ – specified when creating the initial handle to the session, is storedin iSessionType and is validated against the ‘‘sharability’’ level theserver supports. To share this session with other threads, the session haseither to explicitly create a session that supports the level of sharabilityrequired (the preferred method) or subsequently call ShareAuto() (toshare within process) or ShareProtected() (to share between processes), as required. If the ShareXxx() method succeeds, it creates anew process-relative handle and closes the old one.
The new sessioncreation overloads that allow the ‘‘sharability’’ of a session to be specified from session creation are the preferred method, as they avoid theexpensive operation of creating a new handle where it is not needed.These new session creation overloads also support an optional securitypolicy that the client can use to verify the security credentials of the serverit is connecting to. Similarly, there are overloads of the new APIs to open ahandle to a session shared over client-server IPC or from a creator processwhich allow the session to be validated against a security policy.