d3aa74a2f6
Nothing cleaned up this port when the creating isolate died, so the port itself and the last unjoined thread in the corresponding thread pool were leaked until VM shutdown.
Cf. 42d796f7c1
TEST=testandalone/io/leak_io_service_test
Change-Id: Icea27804baf9175b1ff5eb9c50970e0f8d07de2c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/437160
Reviewed-by: Brian Quinlan <bquinlan@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
92 lines
3.0 KiB
C++
92 lines
3.0 KiB
C++
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#if !defined(DART_IO_SECURE_SOCKET_DISABLED)
|
|
|
|
#include "bin/io_service.h"
|
|
|
|
#include "bin/dartutils.h"
|
|
#include "bin/directory.h"
|
|
#include "bin/file.h"
|
|
#include "bin/io_buffer.h"
|
|
#include "bin/secure_socket_filter.h"
|
|
#include "bin/security_context.h"
|
|
#include "bin/socket.h"
|
|
#include "bin/utils.h"
|
|
|
|
#include "include/dart_api.h"
|
|
|
|
#include "platform/globals.h"
|
|
#include "platform/utils.h"
|
|
|
|
namespace dart {
|
|
namespace bin {
|
|
|
|
#define CASE_REQUEST(type, method, id) \
|
|
case IOService::k##type##method##Request: \
|
|
response = type::method##Request(data); \
|
|
break;
|
|
|
|
void IOServiceCallback(Dart_Port dest_port_id, Dart_CObject* message) {
|
|
Dart_Port reply_port_id = ILLEGAL_PORT;
|
|
CObject* response = CObject::IllegalArgumentError();
|
|
CObjectArray request(message);
|
|
if ((message->type == Dart_CObject_kArray) && (request.Length() == 4) &&
|
|
request[0]->IsInt32() && request[1]->IsSendPort() &&
|
|
request[2]->IsInt32() && request[3]->IsArray()) {
|
|
CObjectInt32 message_id(request[0]);
|
|
CObjectSendPort reply_port(request[1]);
|
|
CObjectInt32 request_id(request[2]);
|
|
CObjectArray data(request[3]);
|
|
reply_port_id = reply_port.Value();
|
|
switch (request_id.Value()) {
|
|
IO_SERVICE_REQUEST_LIST(CASE_REQUEST);
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
}
|
|
|
|
CObjectArray result(CObject::NewArray(2));
|
|
result.SetAt(0, request[0]);
|
|
result.SetAt(1, response);
|
|
ASSERT(reply_port_id != ILLEGAL_PORT);
|
|
Dart_PostCObject(reply_port_id, result.AsApiCObject());
|
|
}
|
|
|
|
intptr_t IOService::max_concurrency_ = 32;
|
|
std::atomic<Dart_Port> IOService::port_ = ILLEGAL_PORT;
|
|
|
|
Dart_Port IOService::GetServicePort() {
|
|
Dart_Port port = port_;
|
|
if (port == ILLEGAL_PORT) {
|
|
port = Dart_NewConcurrentNativePort("IOService", IOServiceCallback,
|
|
max_concurrency_);
|
|
Dart_Port expected = ILLEGAL_PORT;
|
|
if (!port_.compare_exchange_strong(expected, port)) {
|
|
// Lost the initialization race. Use the winner's port and close our port.
|
|
// The winner's port is eventually implicitly closed by VM shutdown.
|
|
Dart_CloseNativePort(port);
|
|
return expected;
|
|
}
|
|
}
|
|
return port;
|
|
}
|
|
|
|
void FUNCTION_NAME(IOService_NewServicePort)(Dart_NativeArguments args) {
|
|
Dart_Port service_port = IOService::GetServicePort();
|
|
if (service_port != ILLEGAL_PORT) {
|
|
// Return a send port for the service port.
|
|
Dart_Handle send_port = Dart_NewSendPort(service_port);
|
|
Dart_SetReturnValue(args, send_port);
|
|
} else {
|
|
// If port is not successfully created throw an error.
|
|
Dart_PropagateError(DartUtils::NewError("Unable to create native port"));
|
|
}
|
|
}
|
|
|
|
} // namespace bin
|
|
} // namespace dart
|
|
|
|
#endif // !defined(DART_IO_SECURE_SOCKET_DISABLED)
|