Only join a previous command thread and restart if it has exited

* APP_CMD_INIT_WINDOW can be called when the application hasn't fully
  shutdown, and the thread is still running. Hold a lock while we're
  inside renderdoccmd() so that we know if the thread has exited or not.
* This would be easier if android had pthread_tryjoin_np()...
This commit is contained in:
baldurk
2018-01-22 12:20:15 +00:00
parent e0aedf1f5b
commit 6fe179bea3
+51 -18
View File
@@ -47,11 +47,26 @@ using std::istringstream;
struct android_app *android_state;
pthread_t cmdthread_handle = 0;
struct
struct PThreadLock
{
pthread_mutex_t lock;
pthread_mutexattr_t attr;
} m_DrawLock;
void init()
{
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex, &mutexattr);
}
void destroy()
{
pthread_mutex_destroy(&mutex);
pthread_mutexattr_destroy(&mutexattr);
}
bool trylock() { return pthread_mutex_trylock(&mutex) == 0; };
void lock() { pthread_mutex_lock(&mutex); }
void unlock() { pthread_mutex_unlock(&mutex); }
private:
pthread_mutex_t mutex;
pthread_mutexattr_t mutexattr;
} m_DrawLock, m_CmdLock;
void Daemonise()
{
@@ -60,7 +75,7 @@ void Daemonise()
void DisplayGenericSplash()
{
// if something else is drawing and holding the lock, then bail
if(pthread_mutex_trylock(&m_DrawLock.lock))
if(!m_DrawLock.trylock())
return;
// since we're not pumping this continually and we only draw when we need to, we can just do the
@@ -275,7 +290,7 @@ void main()
dlclose(libEGL);
pthread_mutex_unlock(&m_DrawLock.lock);
m_DrawLock.unlock();
}
WindowingData DisplayRemoteServerPreview(bool active, const rdcarray<WindowingSystem> &systems)
@@ -290,11 +305,11 @@ WindowingData DisplayRemoteServerPreview(bool active, const rdcarray<WindowingSy
// if we're opening it, aquire the draw lock, otherwise release it.
if(active)
{
pthread_mutex_lock(&m_DrawLock.lock);
m_DrawLock.lock();
}
else
{
pthread_mutex_unlock(&m_DrawLock.lock);
m_DrawLock.unlock();
// when we release it, re-draw the splash
DisplayGenericSplash();
@@ -314,7 +329,7 @@ void DisplayRendererPreview(IReplayController *renderer, TextureDisplay &display
{
ANativeWindow *connectionScreenWindow = android_state->window;
pthread_mutex_lock(&m_DrawLock.lock);
m_DrawLock.lock();
IReplayOutput *out = renderer->CreateOutput(CreateAndroidWindowingData(connectionScreenWindow),
ReplayOutputType::Texture);
@@ -331,7 +346,7 @@ void DisplayRendererPreview(IReplayController *renderer, TextureDisplay &display
usleep(100000);
}
pthread_mutex_unlock(&m_DrawLock.lock);
m_DrawLock.unlock();
}
// Returns the renderdoccmd arguments passed via am start
@@ -377,7 +392,11 @@ void *cmdthread(void *)
{
vector<string> args = getRenderdoccmdArgs();
if(args.size())
{
m_CmdLock.lock();
renderdoccmd(GlobalEnvironment(), args);
m_CmdLock.unlock();
}
// activity is done and should be closed
ANativeActivity_finish(android_state->activity);
@@ -391,11 +410,26 @@ void handle_cmd(android_app *app, int32_t cmd)
{
case APP_CMD_INIT_WINDOW:
{
// if we already have a thread handle, see if it's still running
if(cmdthread_handle != 0)
// If user resumes APK after server shutdown, restart the thread.
pthread_join(cmdthread_handle, NULL);
{
// if the thread isn't running anymore, we can acquire m_CmdLock. If so, we need to join the
// thread and start afresh. If we can't acquire the lock, the thread is still running so we
// leave it alone.
if(m_CmdLock.trylock())
{
m_CmdLock.unlock();
// safe to join here, thread will terminate soon if it hasn't already
pthread_join(cmdthread_handle, NULL);
cmdthread_handle = 0;
}
}
pthread_create(&cmdthread_handle, NULL, cmdthread, NULL);
// if we don't have a command thread, start one.
if(cmdthread_handle == 0)
pthread_create(&cmdthread_handle, NULL, cmdthread, NULL);
DisplayGenericSplash();
break;
}
case APP_CMD_WINDOW_REDRAW_NEEDED:
@@ -413,9 +447,8 @@ void android_main(struct android_app *state)
android_state = state;
android_state->onAppCmd = handle_cmd;
pthread_mutexattr_init(&m_DrawLock.attr);
pthread_mutexattr_settype(&m_DrawLock.attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_DrawLock.lock, &m_DrawLock.attr);
m_DrawLock.init();
m_CmdLock.init();
ANDROID_LOG("android_main android_state->window: %p", android_state->window);
@@ -433,6 +466,6 @@ void android_main(struct android_app *state)
ANDROID_LOG("android_main exiting");
pthread_mutex_destroy(&m_DrawLock.lock);
pthread_mutexattr_destroy(&m_DrawLock.attr);
m_DrawLock.destroy();
m_CmdLock.destroy();
}