gecko-dev/hal/gonk/SystemService.cpp
Nicholas Nethercote 34dcc7b852 Bug 1299384 - Use MOZ_MUST_USE with NS_warn_if_impl(). r=erahm.
This change avoids lots of false positives for Coverity's CHECKED_RETURN
warning, caused by NS_WARN_IF's current use in both statement-style and
expression-style.

In the case where the code within the NS_WARN_IF has side-effects, I made the
following change.

> NS_WARN_IF(NS_FAILED(FunctionWithSideEffects()));
> -->
> Unused << NS_WARN_IF(NS_FAILED(FunctionWithSideEffects()));

In the case where the code within the NS_WARN_IF lacks side-effects, I made the
following change.

> NS_WARN_IF(!condWithoutSideEffects);
> -->
> NS_WARNING_ASSERTION(condWithoutSideEffects, "msg");

This has two improvements.
- The condition is not evaluated in non-debug builds.
- The sense of the condition is inverted to the familiar "this condition should
  be true" sense used in assertions.

A common variation on the side-effect-free case is the following.

> nsresult rv = Fn();
> NS_WARN_IF_(NS_FAILED(rv));
> -->
> DebugOnly<nsresult rv> = Fn();
> NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Fn failed");

--HG--
extra : rebase_source : 58788245021096efa8372a9dc1d597a611d45611
2016-09-02 17:12:24 +10:00

132 lines
3.3 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Hal.h"
#include <cutils/properties.h>
#include <stdio.h>
#include <string.h>
#include "HalLog.h"
#include "nsITimer.h"
#include "mozilla/Unused.h"
namespace mozilla {
namespace hal_impl {
static const int sRetryInterval = 100; // ms
bool
SystemServiceIsRunning(const char* aSvcName)
{
MOZ_ASSERT(NS_IsMainThread());
char key[PROPERTY_KEY_MAX];
auto res = snprintf(key, sizeof(key), "init.svc.%s", aSvcName);
if (res < 0) {
HAL_ERR("snprintf: %s", strerror(errno));
return false;
} else if (static_cast<size_t>(res) >= sizeof(key)) {
HAL_ERR("snprintf: trunctated service name %s", aSvcName);
return false;
}
char value[PROPERTY_VALUE_MAX];
Unused << NS_WARN_IF(property_get(key, value, "") < 0);
return !strcmp(value, "running");
}
class StartSystemServiceTimerCallback final : public nsITimerCallback
{
NS_DECL_THREADSAFE_ISUPPORTS;
public:
StartSystemServiceTimerCallback(const char* aSvcName, const char* aArgs)
: mSvcName(aSvcName)
, mArgs(aArgs)
{
MOZ_COUNT_CTOR_INHERITED(StartSystemServiceTimerCallback,
nsITimerCallback);
}
NS_IMETHOD Notify(nsITimer* aTimer) override
{
MOZ_ASSERT(NS_IsMainThread());
return StartSystemService(mSvcName.get(), mArgs.get());
}
protected:
~StartSystemServiceTimerCallback()
{
MOZ_COUNT_DTOR_INHERITED(StartSystemServiceTimerCallback,
nsITimerCallback);
}
private:
nsCString mSvcName;
nsCString mArgs;
};
NS_IMPL_ISUPPORTS0(StartSystemServiceTimerCallback);
nsresult
StartSystemService(const char* aSvcName, const char* aArgs)
{
MOZ_ASSERT(NS_IsMainThread());
char value[PROPERTY_VALUE_MAX];
auto res = snprintf(value, sizeof(value), "%s:%s", aSvcName, aArgs);
if (res < 0) {
HAL_ERR("snprintf: %s", strerror(errno));
return NS_ERROR_FAILURE;
} else if (static_cast<size_t>(res) >= sizeof(value)) {
HAL_ERR("snprintf: trunctated service name %s", aSvcName);
return NS_ERROR_OUT_OF_MEMORY;
}
if (NS_WARN_IF(property_set("ctl.start", value) < 0)) {
return NS_ERROR_FAILURE;
}
/* If the system service is not running, re-try later to start it.
*
* This condition happens when we restart a service immediately
* after it crashed, as the service state remains 'stopping'
* instead of 'stopped'. Due to the limitation of property service,
* hereby add delay. See Bug 1143925 Comment 41.
*/
if (!SystemServiceIsRunning(aSvcName)) {
nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
if (!timer) {
return NS_ERROR_FAILURE;
}
RefPtr<StartSystemServiceTimerCallback> timerCallback =
new StartSystemServiceTimerCallback(aSvcName, aArgs);
timer->InitWithCallback(timerCallback,
sRetryInterval,
nsITimer::TYPE_ONE_SHOT);
}
return NS_OK;
}
void
StopSystemService(const char* aSvcName)
{
MOZ_ASSERT(NS_IsMainThread());
Unused << NS_WARN_IF(property_set("ctl.stop", aSvcName));
}
} // namespace hal_impl
} // namespace mozilla