Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/socket/client_socket_pool_base.h" | 5 #include "net/socket/client_socket_pool_base.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 895 OnAvailableSocketSlot(group_name, group); | 895 OnAvailableSocketSlot(group_name, group); |
| 896 } else { | 896 } else { |
| 897 socket.reset(); | 897 socket.reset(); |
| 898 RecordIdleSocketFate(IDLE_SOCKET_FATE_RELEASE_UNUSABLE); | 898 RecordIdleSocketFate(IDLE_SOCKET_FATE_RELEASE_UNUSABLE); |
| 899 } | 899 } |
| 900 | 900 |
| 901 CheckForStalledSocketGroups(); | 901 CheckForStalledSocketGroups(); |
| 902 } | 902 } |
| 903 | 903 |
| 904 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { | 904 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { |
| 905 // If we have idle sockets, see if we can give one to the top-stalled group. | 905 // Loop until there's nothing more to do. |
| 906 std::string top_group_name; | 906 while (true) { |
| 907 Group* top_group = NULL; | 907 // If we have idle sockets, see if we can give one to the top-stalled group. |
| 908 if (!FindTopStalledGroup(&top_group, &top_group_name)) { | 908 std::string top_group_name; |
| 909 // There may still be a stalled group in a lower level pool. | 909 Group* top_group = NULL; |
| 910 for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin(); | 910 if (!FindTopStalledGroup(&top_group, &top_group_name)) { |
| 911 it != lower_pools_.end(); | 911 // There may still be a stalled group in a lower level pool. |
| 912 ++it) { | 912 for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin(); |
| 913 if ((*it)->IsStalled()) { | 913 it != lower_pools_.end(); ++it) { |
| 914 CloseOneIdleSocket(); | 914 if ((*it)->IsStalled()) { |
| 915 break; | 915 CloseOneIdleSocket(); |
| 916 } | 916 break; |
|
davidben
2017/05/18 20:22:51
What's causing the socket pools to react to the fr
mmenke
2017/05/18 20:44:57
Destroying the socket will do that.
So suppose th
davidben
2017/05/18 20:52:31
I guess the vague analogy to our sync-return || ER
mmenke
2017/05/18 21:00:43
Ideally, we really should only have at most one (n
| |
| 917 } | 917 } |
| 918 return; | 918 } |
| 919 } | |
| 920 | |
| 921 if (ReachedMaxSocketsLimit()) { | |
| 922 if (idle_socket_count() > 0) { | |
| 923 CloseOneIdleSocket(); | |
| 924 } else { | |
| 925 // We can't activate more sockets since we're already at our global | |
| 926 // limit. | |
| 927 return; | 919 return; |
| 928 } | 920 } |
| 921 | |
| 922 if (ReachedMaxSocketsLimit()) { | |
| 923 if (idle_socket_count() > 0) { | |
| 924 CloseOneIdleSocket(); | |
| 925 } else { | |
| 926 // We can't activate more sockets since we're already at our global | |
| 927 // limit. | |
| 928 return; | |
| 929 } | |
| 930 } | |
| 931 | |
| 932 // Note that this may delete top_group. | |
| 933 OnAvailableSocketSlot(top_group_name, top_group); | |
| 929 } | 934 } |
| 930 | |
| 931 // Note: we don't loop on waking stalled groups. If the stalled group is at | |
| 932 // its limit, may be left with other stalled groups that could be | |
| 933 // woken. This isn't optimal, but there is no starvation, so to avoid | |
| 934 // the looping we leave it at this. | |
|
davidben
2017/05/18 20:22:51
Previously we tried to avoid infinite looping here
mmenke
2017/05/18 20:44:57
Correct. I can't see how we'd get into an infinit
| |
| 935 OnAvailableSocketSlot(top_group_name, top_group); | |
| 936 } | 935 } |
| 937 | 936 |
| 938 // Search for the highest priority pending request, amongst the groups that | 937 // Search for the highest priority pending request, amongst the groups that |
| 939 // are not at the |max_sockets_per_group_| limit. Note: for requests with | 938 // are not at the |max_sockets_per_group_| limit. Note: for requests with |
| 940 // the same priority, the winner is based on group hash ordering (and not | 939 // the same priority, the winner is based on group hash ordering (and not |
| 941 // insertion order). | 940 // insertion order). |
| 942 bool ClientSocketPoolBaseHelper::FindTopStalledGroup( | 941 bool ClientSocketPoolBaseHelper::FindTopStalledGroup( |
| 943 Group** group, | 942 Group** group, |
| 944 std::string* group_name) const { | 943 std::string* group_name) const { |
| 945 CHECK((group && group_name) || (!group && !group_name)); | 944 CHECK((group && group_name) || (!group && !group_name)); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1073 | 1072 |
| 1074 // If the group has no idle sockets, and can't make use of an additional slot, | 1073 // If the group has no idle sockets, and can't make use of an additional slot, |
| 1075 // either because it's at the limit or because it's at the socket per group | 1074 // either because it's at the limit or because it's at the socket per group |
| 1076 // limit, then there's nothing to do. | 1075 // limit, then there's nothing to do. |
| 1077 if (group->idle_sockets().empty() && | 1076 if (group->idle_sockets().empty() && |
| 1078 !group->CanUseAdditionalSocketSlot(max_sockets_per_group_)) { | 1077 !group->CanUseAdditionalSocketSlot(max_sockets_per_group_)) { |
| 1079 return; | 1078 return; |
| 1080 } | 1079 } |
| 1081 | 1080 |
| 1082 int rv = RequestSocketInternal(group_name, *next_request); | 1081 int rv = RequestSocketInternal(group_name, *next_request); |
| 1083 if (rv != ERR_IO_PENDING) { | 1082 if (rv != ERR_IO_PENDING) { |
|
mmenke
2017/05/18 20:00:19
Could add a loop here, too, but:
1) group may be
| |
| 1084 std::unique_ptr<Request> request = group->PopNextPendingRequest(); | 1083 std::unique_ptr<Request> request = group->PopNextPendingRequest(); |
| 1085 DCHECK(request); | 1084 DCHECK(request); |
| 1086 if (group->IsEmpty()) | 1085 if (group->IsEmpty()) |
| 1087 RemoveGroup(group_name); | 1086 RemoveGroup(group_name); |
| 1088 | 1087 |
| 1089 request->net_log().EndEventWithNetErrorCode(NetLogEventType::SOCKET_POOL, | 1088 request->net_log().EndEventWithNetErrorCode(NetLogEventType::SOCKET_POOL, |
| 1090 rv); | 1089 rv); |
| 1091 InvokeUserCallbackLater(request->handle(), request->callback(), rv); | 1090 InvokeUserCallbackLater(request->handle(), request->callback(), rv); |
| 1092 } | 1091 } |
| 1093 } | 1092 } |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1480 // If there are no more requests, kill the backup timer. | 1479 // If there are no more requests, kill the backup timer. |
| 1481 if (pending_requests_.empty()) | 1480 if (pending_requests_.empty()) |
| 1482 backup_job_timer_.Stop(); | 1481 backup_job_timer_.Stop(); |
| 1483 request->CrashIfInvalid(); | 1482 request->CrashIfInvalid(); |
| 1484 return request; | 1483 return request; |
| 1485 } | 1484 } |
| 1486 | 1485 |
| 1487 } // namespace internal | 1486 } // namespace internal |
| 1488 | 1487 |
| 1489 } // namespace net | 1488 } // namespace net |
| OLD | NEW |