Skip to content

Commit

Permalink
Bug 1837907 [Linux] Catch SIGTERM in nsAppShell and terminate Firefox…
Browse files Browse the repository at this point in the history
… by standard way r=jld

SIGTERM is supposed to be a standard way how to terminate Linux application. So don't fire emergency exit but run usual exit sequence.

Depends on D191077

Differential Revision: https://phabricator.services.mozilla.com/D191079
  • Loading branch information
stransky committed Nov 29, 2023
1 parent dd2f04e commit ca66547
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 3 deletions.
50 changes: 47 additions & 3 deletions widget/gtk/nsAppShell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ using mozilla::widget::ScreenHelperGTK;
using mozilla::widget::ScreenManager;

#define NOTIFY_TOKEN 0xFA
#define QUIT_TOKEN 0xFB

LazyLogModule gWidgetLog("Widget");
LazyLogModule gWidgetDragLog("WidgetDrag");
Expand All @@ -56,6 +57,8 @@ LazyLogModule gClipboardLog("WidgetClipboard");

static GPollFunc sPollFunc;

nsAppShell* sAppShell = nullptr;

// Wrapper function to disable hang monitoring while waiting in poll().
static gint PollWrapper(GPollFD* aUfds, guint aNfsd, gint aTimeout) {
if (aTimeout == 0) {
Expand Down Expand Up @@ -142,9 +145,17 @@ gboolean nsAppShell::EventProcessorCallback(GIOChannel* source,

unsigned char c;
Unused << read(self->mPipeFDs[0], &c, 1);
NS_ASSERTION(c == (unsigned char)NOTIFY_TOKEN, "wrong token");

self->NativeEventCallback();
switch (c) {
case NOTIFY_TOKEN:
self->NativeEventCallback();
break;
case QUIT_TOKEN:
self->Exit();
break;
default:
NS_ASSERTION(false, "wrong token");
break;
}
return TRUE;
}

Expand Down Expand Up @@ -312,6 +323,30 @@ void nsAppShell::StopDBusListening() {
}
#endif

void nsAppShell::TermSignalHandler(int signo) {
if (signo != SIGTERM) {
NS_WARNING("Wrong signal!");
return;
}
sAppShell->ScheduleQuitEvent();
}

void nsAppShell::InstallTermSignalHandler() {
struct sigaction act = {}, oldact;
act.sa_handler = TermSignalHandler;
sigfillset(&act.sa_mask);

if (NS_WARN_IF(sigaction(SIGTERM, nullptr, &oldact) != 0)) {
return;
}
if (oldact.sa_handler != SIG_DFL) {
NS_WARNING("SIGTERM signal handler is already set?");
}

sigaction(SIGTERM, &act, nullptr);
sAppShell = this;
}

nsresult nsAppShell::Init() {
mozilla::hal::Init();

Expand Down Expand Up @@ -411,6 +446,10 @@ nsresult nsAppShell::Init() {
mTag = g_source_attach(source, nullptr);
g_source_unref(source);

if (XRE_IsParentProcess() && !PR_GetEnv("MOZ_DISABLE_SIG_HANDLER")) {
InstallTermSignalHandler();
}

return nsBaseAppShell::Init();
failed:
close(mPipeFDs[0]);
Expand Down Expand Up @@ -444,3 +483,8 @@ bool nsAppShell::ProcessNextNativeEvent(bool mayWait) {
bool didProcessEvent = g_main_context_iteration(nullptr, mayWait);
return didProcessEvent;
}

void nsAppShell::ScheduleQuitEvent() {
unsigned char buf[] = {QUIT_TOKEN};
Unused << write(mPipeFDs[1], buf, 1);
}
5 changes: 5 additions & 0 deletions widget/gtk/nsAppShell.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ class nsAppShell : public nsBaseAppShell {

static gboolean EventProcessorCallback(GIOChannel* source,
GIOCondition condition, gpointer data);
void InstallTermSignalHandler();
static void TermSignalHandler(int signo);

void ScheduleQuitEvent();

int mPipeFDs[2] = {0, 0};
unsigned mTag = 0;

Expand Down

0 comments on commit ca66547

Please sign in to comment.