Occasionally, if amd does not receive the app dead signal from launchpad due to a delay in dbus
initialization, amd may have a problem of not recognizing the termination status of an app.
To prevent this situation, this patch registers a timer for the startup signal and recognizes that
the app is dead if the signal is not received within 30 seconds.
Change-Id: I3cd0080dcb7148ac4d904639a1bf60d940448a79
Signed-off-by: Changgyu Choi <changyu.choi@samsung.com>
return -1;
app_status->SetStarting(true);
+ app_status->UnsetStartupTimer();
if (app_status->GetAppType() == AT_UI_APP &&
app_status->GetStatus() != STATUS_VISIBLE)
amd::ForegroundManager::GetInst().Add(pid);
namespace {
constexpr int DYING_TIMEOUT = 5;
+constexpr int STARTUP_TIMEOUT = 30;
typedef enum {
AT_SERVICE_APP,
AppStatus::~AppStatus() {
if (dying_timer_ != 0)
g_source_remove(dying_timer_);
+
+ if (startup_timer_ != 0)
+ g_source_remove(startup_timer_);
}
gboolean AppStatus::DyingTimeoutHandler(gpointer data) {
}
}
+void AppStatus::SetStartupTimer() {
+ if (startup_timer_ != 0)
+ return;
+
+ startup_timer_ = g_timeout_add_seconds(STARTUP_TIMEOUT,
+ +[](gpointer data) -> gboolean {
+ auto* app_status = static_cast<AppStatus*>(data);
+ app_status->startup_timer_ = 0;
+ app_status->event_listener_->OnStartupTimeout(app_status);
+ return G_SOURCE_REMOVE;
+ }, this);
+
+ if (startup_timer_ == 0) {
+ _E("Failed to set timeout callback");
+ return;
+ }
+}
+
+void AppStatus::UnsetStartupTimer() {
+ if (startup_timer_ == 0)
+ return;
+
+ g_source_remove(startup_timer_);
+ startup_timer_ = 0;
+}
+
const AppInfo* AppStatus::GetAppInfo() const {
return app_info_.get();
}
class IEvent {
public:
virtual void OnDyingTimeout(AppStatus* data) = 0;
+ virtual void OnStartupTimeout(AppStatus* data) = 0;
virtual ~IEvent() = default;
};
void SetDyingEvent();
+ void SetStartupTimer();
+ void UnsetStartupTimer();
+
unsigned int GetRequestID() const;
void SetPID(pid_t pid);
int timestamp_ = 0;
int fg_count_ = 0;
guint dying_timer_ = 0;
+ guint startup_timer_ = 0;
bool socket_exists_ = false;
bool starting_ = false;
bool exiting_ = false;
}
}
+void AppStatusManager::OnStartupTimeout(AppStatus* app_status) {
+ if (app_status == nullptr)
+ return;
+
+ _E("App startup signal has not been received. pid(%d)", app_status->GetPID());
+ /*
+ Note: When OnStartupTimeout() is called, it may be after the app has
+ already been terminated. In this case, if sigkill is called, there is a
+ possibility that another process executed with the same pid will be
+ killed.
+ */
+ amd::AppStatusManager::GetInst().Update(app_status->shared_from_this(),
+ STATUS_DYING, false, true);
+}
+
AppStatusManager& AppStatusManager::GetInst() {
static AppStatusManager inst;
return inst;
if (app_status == nullptr)
return nullptr;
+ if (!app_status->IsStarting())
+ app_status->SetStartupTimer();
+
_noti_send(AMD_NOTI_MSG_APP_STATUS_ADD, 0, 0, app_status.get(), nullptr);
app_status_dao_->UpdateAppStatus(app_status);
Insert(app_status);
int Finish();
void OnDyingTimeout(AppStatus* app) override;
+ void OnStartupTimeout(AppStatus* app) override;
private:
AppStatusManager() = default;