Skip to content
This repository has been archived by the owner on Apr 10, 2024. It is now read-only.

Race conditions

SomkaPe edited this page May 26, 2020 · 2 revisions

Due to unreliable nature of file locks on mac + Linux next race conditions might happen:

Lost updates.

  • Lost Save tokens cache update

Majority of token cache updates happens in context of silent calls (when RT is used), So result of failed save tokens operation is additional MSAL request to token endpoint. If update is executed in context of login operation (interactive call) – result of lost update is additional request to user to log in. Both cases are not critical, can be tolerated.

  • Lost remove account cache update. This type of lost update is dangerous, cause might lead to deceiving behavior of MSAL SDK - remove account operation can be executed successfully but not be reflected in the persistent state of the cache – application user might execute log out operation successfully but stay signed in.

In order to guarantee account removal by MSAL SDK, remove account API need to confirm successful removal of account – one way to do it is re-read persistent cache to confirm that account removed and update was not lost.

Update of Key Chain entities is subject for race conditions:

  1. check if key chain entity exists using SecKeychainFindGenericPassword
  2. if exists call SecKeychainItemModifyContent, If not call SecKeychainAddGenericPassword

If entity is updates by parallel execution between step 1 and 2 exception is thrown - KeyChainAccessException: The specified item could not be found in the keychain or Item already exists exception. In practice this happens rarely, in order to reproduce insert some delay between 1 and 2 steps.

Taking to account how rear this race condition is, simple retry logic on KeyChainAccessor level should be good enough here.

Dirty reads/writes, cache corruption.

If cache read / write operations are not atomic and cross-process lock is not 100 % reliable, dirty reads/writes might happens which leads to cache corruption.

Key Chain and Key Ring operations are atomic, file reads / writes are not.

So, cache persistence in file on Linux (file lock are not 100% reliable) is subject to dirty reads/writes -> cache corruption.

One way to deal with this is switching from non-atomic file writes to atomic file renaming: Instead of writing cache content to cache file directly, write updated cache file to temporary file (with randomly generated name), than rename temporary file to cache file name – atomic file system operation.