Rework security_manager_sync_threads_internal()
Add "stop-the-world" implemenation in signal handler.
Why this change may be needed?
------------------------------
On slower platforms, some dotnet-based app candidate processes
tend to have 10-15-... threads. Sending signals that change
Smack labels & drop caps to each of them can be delayed - for apps
that don't have a priority to get launched, this can take up
to 10-15 seconds, in pathological cases (observed in real life,
on low-end boards). In such situation, there's non-zero time window
when some threads have changed security attributes and some
haven't - access control issues occur in app candidate's logic,
leading to serious errors & abort()s in the launched app.
With this modification, threads change the Smack labels & capabilities
when none of them are performing any of their original app candidate
logic and the only thread NOT in signal handler is the one
with security-manager client library.
This is expected to limit Smack/permission issues mentioned earlier.
Details, disclaimers:
---------------------
This implementation CANNOT fix an issue where app candidate process
created a resource (ie. a file) BEFORE call to security_manager_prepare_app()
and then, wants to access it (for read) AFTER call to the function.
This is because, before the transition, the process has either User
or System::Privileged Smack label, to which apps do not have R Smack rule
(such issues can still occur and can't be dealt with at security-manger level).
This implementation can be up to 3x slower on low-end boards,
as we have 3 waiting points here, instead of one:
1) waiting for signals to arrive in all threads (place from old implementation)
2) waiting for signals to be able to start changing caps/Smack labels
3) waiting for signals to sync after attributes are changed to start work
Tests performed on Tizen emulator show about 30-40% slowdown
of prepare app vs. previous implementation.
This implementation assumes that the size of set of all TIDs
that can appear in a process (already dead + currently alive) will not exceed 1000.
A global array of std::atomic's is used to keep track of each thread's
state in the execution of signal handler.
This implementation uses sleep() and std::atomic to implement
waiting for the barrier inside a signal handler (home-made spinlock,
basically). While this can be done more elegantly, ie. with std::atomic's wait()
functionality, this C++ feature doesn't seem to be supported in current Tizen
toolchain (c++2a supported, not full c++20).
An alternative way for synchronization would be to use high-profile system
resources like fd's or semaphores, however, because the VD H/W platform
where the issue of thread dis-synchronization happens is very slow, interfacing
with kernel was limited to minimum, as adding any context switch to kernel
may slow down even more.
Change-Id: Ic7037acaeb4e3eaab03284ae63216e7ab4d6d862