зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1658084
- Avoid creating a mozilla::OffTheBooksMutex in a static initializer, r=emilio,mccr8
Differential Revision: https://phabricator.services.mozilla.com/D95660
This commit is contained in:
Родитель
1825576064
Коммит
188a162ad4
|
@ -44,32 +44,21 @@ static bool LoadCupsFunc(PRLibrary*& lib, FuncT*& dest,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool nsCUPSShim::Init() {
|
||||
mozilla::OffTheBooksMutexAutoLock lock(mInitMutex);
|
||||
if (mInited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCUPSShim::nsCUPSShim() {
|
||||
mCupsLib = PR_LoadLibrary(gCUPSLibraryName);
|
||||
if (!mCupsLib) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// This is a macro so that it could also load from libcups if we are configured
|
||||
// to use it as a compile-time dependency.
|
||||
// This is a macro so that it could also load from libcups if we are
|
||||
// configured to use it as a compile-time dependency.
|
||||
# define CUPS_SHIM_LOAD(NAME) \
|
||||
if (!LoadCupsFunc(mCupsLib, NAME, #NAME)) return false;
|
||||
if (!LoadCupsFunc(mCupsLib, NAME, #NAME)) return;
|
||||
CUPS_SHIM_ALL_FUNCS(CUPS_SHIM_LOAD)
|
||||
# undef CUPS_SHIM_LOAD
|
||||
mInited = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
#else // CUPS_SHIM_RUNTIME_LINK
|
||||
|
||||
bool nsCUPSShim::Init() {
|
||||
mInited = true;
|
||||
return true;
|
||||
// Set mInitOkay only if all cups functions are loaded successfully.
|
||||
mInitOkay = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,10 +18,15 @@
|
|||
|
||||
struct PRLibrary;
|
||||
|
||||
/* Note: this class relies on static initialization. */
|
||||
class nsCUPSShim {
|
||||
public:
|
||||
bool EnsureInitialized() { return mInited || Init(); }
|
||||
#ifdef CUPS_SHIM_RUNTIME_LINK
|
||||
nsCUPSShim();
|
||||
bool InitOkay() { return mInitOkay; }
|
||||
#else
|
||||
nsCUPSShim() = default;
|
||||
bool InitOkay() { return true; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Function pointers for supported functions. These are only
|
||||
|
@ -60,7 +65,7 @@ class nsCUPSShim {
|
|||
|
||||
#ifdef CUPS_SHIM_RUNTIME_LINK
|
||||
// Define a single field which holds a function pointer.
|
||||
# define CUPS_SHIM_FUNC_DECL(X) decltype(::X)* X;
|
||||
# define CUPS_SHIM_FUNC_DECL(X) decltype(::X)* X = nullptr;
|
||||
#else
|
||||
// Define a static constexpr function pointer. GCC can sometimes optimize
|
||||
// away the pointer fetch for this.
|
||||
|
@ -70,25 +75,10 @@ class nsCUPSShim {
|
|||
CUPS_SHIM_ALL_FUNCS(CUPS_SHIM_FUNC_DECL)
|
||||
#undef CUPS_SHIM_FUNC_DECL
|
||||
|
||||
private:
|
||||
/**
|
||||
* Initialize this object. Attempt to load the CUPS shared
|
||||
* library and find function pointers for the supported
|
||||
* functions (see below).
|
||||
* @return false if the shared library could not be loaded, or if
|
||||
* any of the functions could not be found.
|
||||
* true for successful initialization.
|
||||
*/
|
||||
bool Init();
|
||||
|
||||
// We can try to get initialized from multiple threads at the same time, this
|
||||
// boolean and the mutex below make it safe.
|
||||
//
|
||||
// The boolean can't be Relaxed, because it guards our function pointers.
|
||||
mozilla::Atomic<bool, mozilla::ReleaseAcquire> mInited{false};
|
||||
#ifdef CUPS_SHIM_RUNTIME_LINK
|
||||
mozilla::OffTheBooksMutex mInitMutex{"nsCUPSShim::mInitMutex"};
|
||||
PRLibrary* mCupsLib;
|
||||
private:
|
||||
bool mInitOkay = false;
|
||||
PRLibrary* mCupsLib = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,13 @@
|
|||
#include "nsString.h"
|
||||
#include "prenv.h"
|
||||
|
||||
static nsCUPSShim sCupsShim;
|
||||
// Use a local static to initialize the CUPS shim lazily, when it's needed.
|
||||
// This is used in order to avoid a global constructor.
|
||||
static nsCUPSShim& CupsShim() {
|
||||
static nsCUPSShim sCupsShim;
|
||||
return sCupsShim;
|
||||
}
|
||||
|
||||
using PrinterInfo = nsPrinterListBase::PrinterInfo;
|
||||
|
||||
/**
|
||||
|
@ -23,8 +29,8 @@ static void GetDisplayNameForPrinter(const cups_dest_t& aDest,
|
|||
// while GTK clients expect non-prettified names.
|
||||
// If you change this, please change NamedPrinter accordingly.
|
||||
#ifdef XP_MACOSX
|
||||
const char* displayName =
|
||||
sCupsShim.cupsGetOption("printer-info", aDest.num_options, aDest.options);
|
||||
const char* displayName = CupsShim().cupsGetOption(
|
||||
"printer-info", aDest.num_options, aDest.options);
|
||||
if (displayName) {
|
||||
CopyUTF8toUTF16(MakeStringSpan(displayName), aName);
|
||||
}
|
||||
|
@ -67,7 +73,7 @@ static int CupsDestCallback(void* user_data, unsigned aFlags,
|
|||
|
||||
cups_dest_t* ownedDest = nullptr;
|
||||
mozilla::DebugOnly<const int> numCopied =
|
||||
sCupsShim.cupsCopyDest(aDest, 0, &ownedDest);
|
||||
CupsShim().cupsCopyDest(aDest, 0, &ownedDest);
|
||||
MOZ_ASSERT(numCopied == 1);
|
||||
|
||||
nsString name;
|
||||
|
@ -79,12 +85,12 @@ static int CupsDestCallback(void* user_data, unsigned aFlags,
|
|||
}
|
||||
|
||||
nsTArray<PrinterInfo> nsPrinterListCUPS::Printers() const {
|
||||
if (!sCupsShim.EnsureInitialized()) {
|
||||
if (!CupsShim().InitOkay()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
nsTArray<PrinterInfo> printerInfoList;
|
||||
if (!sCupsShim.cupsEnumDests(
|
||||
if (!CupsShim().cupsEnumDests(
|
||||
CUPS_DEST_FLAGS_NONE,
|
||||
0 /* timeout, 0 timeout shouldn't be a problem since we are masking
|
||||
CUPS_PRINTER_DISCOVERED */
|
||||
|
@ -100,14 +106,14 @@ nsTArray<PrinterInfo> nsPrinterListCUPS::Printers() const {
|
|||
|
||||
RefPtr<nsIPrinter> nsPrinterListCUPS::CreatePrinter(PrinterInfo aInfo) const {
|
||||
return mozilla::MakeRefPtr<nsPrinterCUPS>(
|
||||
mCommonPaperInfo, sCupsShim, std::move(aInfo.mName),
|
||||
mCommonPaperInfo, CupsShim(), std::move(aInfo.mName),
|
||||
static_cast<cups_dest_t*>(aInfo.mCupsHandle));
|
||||
}
|
||||
|
||||
Maybe<PrinterInfo> nsPrinterListCUPS::PrinterByName(
|
||||
nsString aPrinterName) const {
|
||||
Maybe<PrinterInfo> rv;
|
||||
if (!sCupsShim.EnsureInitialized()) {
|
||||
if (!CupsShim().InitOkay()) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -123,26 +129,26 @@ Maybe<PrinterInfo> nsPrinterListCUPS::PrinterByName(
|
|||
nsAutoCString printerName;
|
||||
CopyUTF16toUTF8(aPrinterName, printerName);
|
||||
cups_dest_t* printers = nullptr;
|
||||
const auto numPrinters = sCupsShim.cupsGetDests(&printers);
|
||||
const auto numPrinters = CupsShim().cupsGetDests(&printers);
|
||||
for (auto i : mozilla::IntegerRange(0, numPrinters)) {
|
||||
const char* const displayName = sCupsShim.cupsGetOption(
|
||||
const char* const displayName = CupsShim().cupsGetOption(
|
||||
"printer-info", printers[i].num_options, printers[i].options);
|
||||
if (printerName == displayName) {
|
||||
// The second arg to sCupsShim.cupsCopyDest is called num_dests, but
|
||||
// The second arg to CupsShim().cupsCopyDest is called num_dests, but
|
||||
// it actually copies num_dests + 1 elements.
|
||||
sCupsShim.cupsCopyDest(printers + i, 0, &printer);
|
||||
CupsShim().cupsCopyDest(printers + i, 0, &printer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
sCupsShim.cupsFreeDests(numPrinters, printers);
|
||||
CupsShim().cupsFreeDests(numPrinters, printers);
|
||||
}
|
||||
#else
|
||||
// On GTK, we only ever show the CUPS name of printers, so we can use
|
||||
// cupsGetNamedDest directly.
|
||||
{
|
||||
const auto printerName = NS_ConvertUTF16toUTF8(aPrinterName);
|
||||
printer = sCupsShim.cupsGetNamedDest(CUPS_HTTP_DEFAULT, printerName.get(),
|
||||
nullptr);
|
||||
printer = CupsShim().cupsGetNamedDest(CUPS_HTTP_DEFAULT, printerName.get(),
|
||||
nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -157,12 +163,12 @@ Maybe<PrinterInfo> nsPrinterListCUPS::PrinterByName(
|
|||
Maybe<PrinterInfo> nsPrinterListCUPS::PrinterBySystemName(
|
||||
nsString aPrinterName) const {
|
||||
Maybe<PrinterInfo> rv;
|
||||
if (!sCupsShim.EnsureInitialized()) {
|
||||
if (!CupsShim().InitOkay()) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
const auto printerName = NS_ConvertUTF16toUTF8(aPrinterName);
|
||||
if (cups_dest_t* const printer = sCupsShim.cupsGetNamedDest(
|
||||
if (cups_dest_t* const printer = CupsShim().cupsGetNamedDest(
|
||||
CUPS_HTTP_DEFAULT, printerName.get(), nullptr)) {
|
||||
rv.emplace(PrinterInfo{std::move(aPrinterName), printer});
|
||||
}
|
||||
|
@ -172,14 +178,14 @@ Maybe<PrinterInfo> nsPrinterListCUPS::PrinterBySystemName(
|
|||
nsresult nsPrinterListCUPS::SystemDefaultPrinterName(nsAString& aName) const {
|
||||
aName.Truncate();
|
||||
|
||||
if (!sCupsShim.EnsureInitialized()) {
|
||||
if (!CupsShim().InitOkay()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Passing in nullptr for the name will return the default, if any.
|
||||
cups_dest_t* dest =
|
||||
sCupsShim.cupsGetNamedDest(CUPS_HTTP_DEFAULT, /* name */ nullptr,
|
||||
/* instance */ nullptr);
|
||||
CupsShim().cupsGetNamedDest(CUPS_HTTP_DEFAULT, /* name */ nullptr,
|
||||
/* instance */ nullptr);
|
||||
if (!dest) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -189,6 +195,6 @@ nsresult nsPrinterListCUPS::SystemDefaultPrinterName(nsAString& aName) const {
|
|||
CopyUTF8toUTF16(mozilla::MakeStringSpan(dest->name), aName);
|
||||
}
|
||||
|
||||
sCupsShim.cupsFreeDests(1, dest);
|
||||
CupsShim().cupsFreeDests(1, dest);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче