forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a per-process limit on open UDP sockets.
This adds a default limit of 6000 on the open UDP sockets throughout the entire process, configurable with the "LimitOpenUDPSockets" feature. An "open UDP socket" specifically means a net::UDPSocket which successfully called Open(), and has not yet called Close(). Once the limit has been reached, opening UDP socket will fail with ERR_INSUFFICIENT_RESOURCES. In Chrome Browser, UDP sockets are brokered through a single process (that hosting the Network Service), so this is functionally a browser-wide limit too. Bug: 1083278 Change-Id: Ib95ab14b7ccf5e15410b9df9537c66c858de2d7d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2350395 Reviewed-by: David Schinazi <dschinazi@chromium.org> Commit-Queue: Eric Roman <eroman@chromium.org> Cr-Commit-Position: refs/heads/master@{#797523}
- Loading branch information
Eric Roman
authored and
Commit Bot
committed
Aug 13, 2020
1 parent
9b80c3e
commit 5a84192
Showing
10 changed files
with
353 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// Copyright 2020 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include <limits> | ||
|
||
#include "base/atomic_ref_count.h" | ||
#include "base/no_destructor.h" | ||
#include "net/base/features.h" | ||
#include "net/socket/udp_socket_global_limits.h" | ||
|
||
namespace net { | ||
|
||
namespace { | ||
|
||
// Threadsafe singleton for tracking the process-wide count of UDP sockets. | ||
class GlobalUDPSocketCounts { | ||
public: | ||
GlobalUDPSocketCounts() : count_(0) {} | ||
|
||
~GlobalUDPSocketCounts() = delete; | ||
|
||
static GlobalUDPSocketCounts& Get() { | ||
static base::NoDestructor<GlobalUDPSocketCounts> singleton; | ||
return *singleton; | ||
} | ||
|
||
bool TryAcquireSocket() WARN_UNUSED_RESULT { | ||
int previous = count_.Increment(1); | ||
if (previous >= GetMax()) { | ||
count_.Increment(-1); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
int GetMax() { | ||
if (base::FeatureList::IsEnabled(features::kLimitOpenUDPSockets)) | ||
return features::kLimitOpenUDPSocketsMax.Get(); | ||
|
||
return std::numeric_limits<int>::max(); | ||
} | ||
|
||
void ReleaseSocket() { count_.Increment(-1); } | ||
|
||
int GetCountForTesting() { return count_.SubtleRefCountForDebug(); } | ||
|
||
private: | ||
base::AtomicRefCount count_; | ||
}; | ||
|
||
} // namespace | ||
|
||
OwnedUDPSocketCount::OwnedUDPSocketCount() : OwnedUDPSocketCount(true) {} | ||
|
||
OwnedUDPSocketCount::OwnedUDPSocketCount(OwnedUDPSocketCount&& other) { | ||
*this = std::move(other); | ||
} | ||
|
||
OwnedUDPSocketCount& OwnedUDPSocketCount::operator=( | ||
OwnedUDPSocketCount&& other) { | ||
Reset(); | ||
empty_ = other.empty_; | ||
other.empty_ = true; | ||
return *this; | ||
} | ||
|
||
OwnedUDPSocketCount::~OwnedUDPSocketCount() { | ||
Reset(); | ||
} | ||
|
||
void OwnedUDPSocketCount::Reset() { | ||
if (!empty_) { | ||
GlobalUDPSocketCounts::Get().ReleaseSocket(); | ||
empty_ = true; | ||
} | ||
} | ||
|
||
OwnedUDPSocketCount::OwnedUDPSocketCount(bool empty) : empty_(empty) {} | ||
|
||
OwnedUDPSocketCount TryAcquireGlobalUDPSocketCount() { | ||
bool success = GlobalUDPSocketCounts::Get().TryAcquireSocket(); | ||
return OwnedUDPSocketCount(!success); | ||
} | ||
|
||
int GetGlobalUDPSocketCountForTesting() { | ||
return GlobalUDPSocketCounts::Get().GetCountForTesting(); | ||
} | ||
|
||
} // namespace net |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// Copyright 2020 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef NET_SOCKET_UDP_SOCKET_GLOBAL_LIMITS_H_ | ||
#define NET_SOCKET_UDP_SOCKET_GLOBAL_LIMITS_H_ | ||
|
||
#include "base/compiler_specific.h" | ||
#include "net/base/net_errors.h" | ||
#include "net/base/net_export.h" | ||
|
||
namespace net { | ||
|
||
// Helper class for RAII-style management of the global count of "open UDP | ||
// sockets" [1] in the process. | ||
// | ||
// Keeping OwnedUDPSocketCount alive increases the global socket counter by 1. | ||
// When it goes out of scope - or is explicitly Reset() - the reference is | ||
// returned to the global counter. | ||
class NET_EXPORT OwnedUDPSocketCount { | ||
public: | ||
// The default constructor builds an empty OwnedUDPSocketCount (does not own a | ||
// count). | ||
OwnedUDPSocketCount(); | ||
|
||
// Any count held by OwnedUDPSocketCount is transferred when moving. | ||
OwnedUDPSocketCount(OwnedUDPSocketCount&&); | ||
OwnedUDPSocketCount& operator=(OwnedUDPSocketCount&&); | ||
|
||
// This is a move-only type. | ||
OwnedUDPSocketCount(const OwnedUDPSocketCount&) = delete; | ||
OwnedUDPSocketCount& operator=(const OwnedUDPSocketCount&) = delete; | ||
|
||
~OwnedUDPSocketCount(); | ||
|
||
// Returns false if this instance "owns" a socket count. In | ||
// other words, when |empty()|, destruction of |this| will | ||
// not change the global socket count. | ||
bool empty() const { return empty_; } | ||
|
||
// Resets |this| to an empty state (|empty()| becomes true after | ||
// calling this). If |this| was previously |!empty()|, the global | ||
// socket count will be decremented. | ||
void Reset(); | ||
|
||
private: | ||
// Only TryAcquireGlobalUDPSocketCount() is allowed to construct a non-empty | ||
// OwnedUDPSocketCount. | ||
friend NET_EXPORT OwnedUDPSocketCount TryAcquireGlobalUDPSocketCount(); | ||
explicit OwnedUDPSocketCount(bool empty); | ||
|
||
bool empty_; | ||
}; | ||
|
||
// Attempts to increase the global "open UDP socket" [1] count. | ||
// | ||
// * On failure returns an OwnedUDPSocketCount that is |empty()|. This happens | ||
// if the global socket limit has been reached. | ||
// * On success returns an OwnedUDPSocketCount that is |!empty()|. This | ||
// OwnedUDPSocketCount should be kept alive until the socket resource is | ||
// released. | ||
// | ||
// [1] For simplicity, an "open UDP socket" is defined as a net::UDPSocket that | ||
// successfully called Open(), and has not yet called Close(). This is | ||
// analogous to the number of open platform socket handles, and in practice | ||
// should also be a good proxy for the number of consumed UDP ports. | ||
NET_EXPORT OwnedUDPSocketCount TryAcquireGlobalUDPSocketCount() | ||
WARN_UNUSED_RESULT; | ||
|
||
// Returns the current count of open UDP sockets (for testing only). | ||
NET_EXPORT int GetGlobalUDPSocketCountForTesting(); | ||
|
||
} // namespace net | ||
|
||
#endif // NET_SOCKET_UDP_SOCKET_GLOBAL_LIMITS_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.