Skip to content

Commit

Permalink
Fixed embedLiteCoreInitTest to exit nice without crashes and leaks
Browse files Browse the repository at this point in the history
  • Loading branch information
tmeshkova committed Nov 26, 2014
1 parent c45a192 commit 03b133f
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 140 deletions.
12 changes: 6 additions & 6 deletions embedding/embedlite/EmbedLiteApp.cpp
Expand Up @@ -18,14 +18,14 @@
#include "EmbedLiteSubThread.h"
#include "GeckoLoader.h"

#include "EmbedLiteSubProcess.h"
#include "EmbedLiteAppThreadParent.h"
#include "EmbedLiteAppThreadChild.h"
#include "EmbedLiteView.h"
#include "nsXULAppAPI.h"
#include "EmbedLiteMessagePump.h"

#include "EmbedLiteCompositorParent.h"
#include "EmbedLiteAppProcessParent.h"

namespace mozilla {
namespace embedlite {
Expand Down Expand Up @@ -137,9 +137,7 @@ EmbedLiteApp::StartChild(EmbedLiteApp* aApp)
}
}
} else if (aApp->mEmbedType == EMBED_PROCESS) {
aApp->mSubProcess = new EmbedLiteSubProcess();
aApp->mSubProcess->StartEmbedProcess();
aApp->mAppParent = aApp->mSubProcess->AppParent();
aApp->mAppParent = EmbedLiteAppProcessParent::CreateEmbedLiteAppProcessParent();
}
}

Expand Down Expand Up @@ -317,8 +315,7 @@ EmbedLiteApp::Shutdown()
"StopChildThread must be implemented when ExecuteChildThread defined");
}
} else if (mEmbedType == EMBED_PROCESS) {
mSubProcess->StopEmbedProcess();
mSubProcess = nullptr;
delete mAppParent;
}
}

Expand Down Expand Up @@ -433,6 +430,9 @@ EmbedLiteApp::ChildReadyToDestroy()
mUILoop->PostTask(FROM_HERE,
NewRunnableFunction(&_FinalStop, this));
}
if (mEmbedType == EMBED_PROCESS) {
mAppParent = nullptr;
}
}

uint32_t
Expand Down
2 changes: 1 addition & 1 deletion embedding/embedlite/EmbedLiteApp.h
Expand Up @@ -25,6 +25,7 @@ class EmbedLiteAppThreadChild;
class EmbedLiteAppThreadParent;
class EmbedLiteSubThread;
class EmbedLiteSubProcess;
class EmbedLiteAppProcessParent;
class EmbedLiteView;
class PEmbedLiteAppParent;
class EmbedLiteAppListener
Expand Down Expand Up @@ -187,7 +188,6 @@ class EmbedLiteApp
RefPtr<EmbedLiteSubThread> mSubThread;
PEmbedLiteAppParent* mAppParent;
RefPtr<EmbedLiteAppThreadChild> mAppChild;
RefPtr<EmbedLiteSubProcess> mSubProcess;

EmbedType mEmbedType;
std::map<uint32_t, EmbedLiteView*> mViews;
Expand Down
15 changes: 15 additions & 0 deletions embedding/embedlite/embedprocess/EmbedLiteAppProcessChild.cpp
Expand Up @@ -18,6 +18,7 @@
#include "nsThreadManager.h"
#include "nsServiceManagerUtils.h"
#include "nsIConsoleService.h"
#include "nsDebugImpl.h"

using namespace base;
using namespace mozilla::ipc;
Expand All @@ -31,6 +32,7 @@ EmbedLiteAppProcessChild* EmbedLiteAppProcessChild::sSingleton;
EmbedLiteAppProcessChild::EmbedLiteAppProcessChild()
{
LOGT();
nsDebugImpl::SetMultiprocessMode("Child");
}

EmbedLiteAppProcessChild::~EmbedLiteAppProcessChild()
Expand Down Expand Up @@ -92,6 +94,19 @@ void
EmbedLiteAppProcessChild::ActorDestroy(ActorDestroyReason aWhy)
{
LOGT("reason:%i", aWhy);
if (AbnormalShutdown == aWhy) {
NS_WARNING("shutting down early because of crash!");
QuickExit();
}

XRE_ShutdownChildProcess();
}

void
EmbedLiteAppProcessChild::QuickExit()
{
NS_WARNING("content process _exit()ing");
_exit(0);
}

PEmbedLiteViewChild*
Expand Down
2 changes: 2 additions & 0 deletions embedding/embedlite/embedprocess/EmbedLiteAppProcessChild.h
Expand Up @@ -65,6 +65,8 @@ class EmbedLiteAppProcessChild : public PEmbedLiteAppChild
virtual bool DeallocPEmbedLiteViewChild(PEmbedLiteViewChild*) MOZ_OVERRIDE;

private:
void QuickExit();

AppInfo mAppInfo;
static EmbedLiteAppProcessChild* sSingleton;

Expand Down
126 changes: 125 additions & 1 deletion embedding/embedlite/embedprocess/EmbedLiteAppProcessParent.cpp
Expand Up @@ -16,6 +16,24 @@
#include <sys/resource.h>
#endif

#include "EmbedLog.h"

#include "nsXPCOMPrivate.h"
#include "GeckoLoader.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "EmbedLiteApp.h"
#include "GeckoProfiler.h"
#include "EmbedLiteAppProcessParent.h"
#include "mozilla/ipc/BrowserProcessSubThread.h"
#include "nsThreadManager.h"
#include "nsAutoPtr.h"
#include "base/command_line.h"
#include "nsDirectoryService.h"
#include "nsDirectoryServiceDefs.h"

static BrowserProcessSubThread* sIOThread;

using namespace mozilla::dom;
using namespace base;
using base::ChildPrivileges;
using base::KillProcess;
Expand All @@ -27,17 +45,67 @@ using namespace mozilla::net;
namespace mozilla {
namespace embedlite {

EmbedLiteAppProcessParent*
EmbedLiteAppProcessParent::CreateEmbedLiteAppProcessParent()
{
LOGT();
// Establish the main thread here.
if (NS_FAILED(nsThreadManager::get()->Init())) {
NS_ERROR("Could not initialize thread manager");
return nullptr;
}

NS_SetMainThread();

return new EmbedLiteAppProcessParent();
}

EmbedLiteAppProcessParent::EmbedLiteAppProcessParent()
: mApp(EmbedLiteApp::GetInstance())
{
LOGT();
MOZ_COUNT_CTOR(EmbedLiteAppProcessParent);

mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content, base::PRIVILEGES_DEFAULT);

PR_SetEnv("NECKO_SEPARATE_STACKS=1");
if (!BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)) {
UniquePtr<BrowserProcessSubThread> ioThread(new BrowserProcessSubThread(BrowserProcessSubThread::IO));
if (!ioThread.get()) {
return;
}

base::Thread::Options options;
options.message_loop_type = MessageLoop::TYPE_IO;
if (!ioThread->StartWithOptions(options)) {
return;
}
sIOThread = ioThread.release();
}

IToplevelProtocol::SetTransport(mSubprocess->GetChannel());

// set gGREBinPath
gGREBinPath = ToNewUnicode(nsDependentCString(getenv("GRE_HOME")));

if (!CommandLine::IsInitialized()) {
CommandLine::Init(0, nullptr);
}

std::vector<std::string> extraArgs;
extraArgs.push_back("-embedlite");
mSubprocess->LaunchAndWaitForProcessHandle(extraArgs);
Open(mSubprocess->GetChannel(), mSubprocess->GetOwnedChildProcessHandle());
}

EmbedLiteAppProcessParent::~EmbedLiteAppProcessParent()
{
LOGT();
MOZ_COUNT_DTOR(EmbedLiteAppProcessParent);
if (OtherProcess())
base::CloseProcessHandle(OtherProcess());

mApp->ChildReadyToDestroy();
}

void
Expand Down Expand Up @@ -96,7 +164,9 @@ bool
EmbedLiteAppProcessParent::RecvReadyToShutdown()
{
LOGT();
mApp->ChildReadyToDestroy();
MessageLoop::current()->PostTask(
FROM_HERE, NewRunnableMethod(this, &EmbedLiteAppProcessParent::ShutDownProcess, /* force */ false));

return true;
}

Expand Down Expand Up @@ -133,10 +203,64 @@ EmbedLiteAppProcessParent::DeallocPEmbedLiteViewParent(PEmbedLiteViewParent* aAc
return false;
}

namespace {

void
DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
{
LOGT();
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<GeckoChildProcessHost>(aSubprocess));
}

// This runnable only exists to delegate ownership of the
// EmbedLiteAppProcessParent to this runnable, until it's deleted by the event
// system.
struct DelayedDeleteContentParentTask : public nsRunnable
{
explicit DelayedDeleteContentParentTask(EmbedLiteAppProcessParent* aObj) : mObj(aObj) { }

// No-op
NS_IMETHODIMP Run() { return NS_OK; }

nsRefPtr<EmbedLiteAppProcessParent> mObj;
};

}

void
EmbedLiteAppProcessParent::ActorDestroy(ActorDestroyReason aWhy)
{
LOGT();

ShutDownProcess(true);

MessageLoop::current()->
PostTask(FROM_HERE,
NewRunnableFunction(DelayedDeleteSubprocess, mSubprocess));
mSubprocess = nullptr;
}

void
EmbedLiteAppProcessParent::ShutDownProcess(bool aCloseWithError)
{
LOGT();
// If Close() fails with an error, we'll end up back in this function, but
// with aCloseWithError = true. It's important that we call
// CloseWithError() in this case; see bug 895204.

if (!aCloseWithError) {
// Close() can only be called once: It kicks off the destruction
// sequence.
Close();
}

if (aCloseWithError) {
MessageChannel* channel = GetIPCChannel();
if (channel) {
channel->CloseWithError();
}
}
}

} // namespace embedlite
Expand Down
9 changes: 8 additions & 1 deletion embedding/embedlite/embedprocess/EmbedLiteAppProcessParent.h
Expand Up @@ -9,14 +9,19 @@
#include "mozilla/embedlite/PEmbedLiteAppParent.h"

namespace mozilla {
namespace ipc {
class GeckoChildProcessHost;
}
namespace embedlite {

class EmbedLiteAppProcessParent : public PEmbedLiteAppParent
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(EmbedLiteAppProcessParent)
public:
EmbedLiteAppProcessParent();

public:
static EmbedLiteAppProcessParent* CreateEmbedLiteAppProcessParent();

protected:
void OnChannelConnected(int32_t pid) MOZ_OVERRIDE;

Expand Down Expand Up @@ -53,8 +58,10 @@ class EmbedLiteAppProcessParent : public PEmbedLiteAppParent

private:
virtual ~EmbedLiteAppProcessParent();
void ShutDownProcess(bool aCloseWithError);

EmbedLiteApp* mApp;
mozilla::ipc::GeckoChildProcessHost* mSubprocess;

DISALLOW_EVIL_CONSTRUCTORS(EmbedLiteAppProcessParent);
};
Expand Down

0 comments on commit 03b133f

Please sign in to comment.