Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: runtime/bin/socket.h

Issue 2760293002: [dart:io] Adds a finalizer to _NativeSocket to avoid socket leaks (Closed)
Patch Set: Address comments Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/bin/reference_counting.h ('k') | runtime/bin/socket.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #ifndef RUNTIME_BIN_SOCKET_H_ 5 #ifndef RUNTIME_BIN_SOCKET_H_
6 #define RUNTIME_BIN_SOCKET_H_ 6 #define RUNTIME_BIN_SOCKET_H_
7 7
8 #if defined(DART_IO_DISABLED) 8 #if defined(DART_IO_DISABLED)
9 #error "socket.h can only be included on builds with IO enabled" 9 #error "socket.h can only be included on builds with IO enabled"
10 #endif 10 #endif
11 11
12 #include "platform/globals.h" 12 #include "platform/globals.h"
13 // Declare the OS-specific types ahead of defining the generic class. 13 // Declare the OS-specific types ahead of defining the generic class.
14 #if defined(HOST_OS_ANDROID) 14 #if defined(HOST_OS_ANDROID)
15 #include "bin/socket_android.h" 15 #include "bin/socket_android.h"
16 #elif defined(HOST_OS_FUCHSIA) 16 #elif defined(HOST_OS_FUCHSIA)
17 #include "bin/socket_fuchsia.h" 17 #include "bin/socket_fuchsia.h"
18 #elif defined(HOST_OS_LINUX) 18 #elif defined(HOST_OS_LINUX)
19 #include "bin/socket_linux.h" 19 #include "bin/socket_linux.h"
20 #elif defined(HOST_OS_MACOS) 20 #elif defined(HOST_OS_MACOS)
21 #include "bin/socket_macos.h" 21 #include "bin/socket_macos.h"
22 #elif defined(HOST_OS_WINDOWS) 22 #elif defined(HOST_OS_WINDOWS)
23 #include "bin/socket_win.h" 23 #include "bin/socket_win.h"
24 #else 24 #else
25 #error Unknown target os. 25 #error Unknown target os.
26 #endif 26 #endif
27 27
28 #include "bin/builtin.h" 28 #include "bin/builtin.h"
29 #include "bin/dartutils.h" 29 #include "bin/dartutils.h"
30 #include "bin/reference_counting.h"
30 #include "bin/thread.h" 31 #include "bin/thread.h"
31 #include "bin/utils.h" 32 #include "bin/utils.h"
32 #include "platform/hashmap.h" 33 #include "platform/hashmap.h"
33 34
34 namespace dart { 35 namespace dart {
35 namespace bin { 36 namespace bin {
36 37
37 union RawAddr { 38 union RawAddr {
38 struct sockaddr_in in; 39 struct sockaddr_in in;
39 struct sockaddr_in6 in6; 40 struct sockaddr_in6 in6;
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 void SetAt(intptr_t i, T* addr) { addresses_[i] = addr; } 241 void SetAt(intptr_t i, T* addr) { addresses_[i] = addr; }
241 242
242 private: 243 private:
243 const intptr_t count_; 244 const intptr_t count_;
244 T** addresses_; 245 T** addresses_;
245 246
246 DISALLOW_COPY_AND_ASSIGN(AddressList); 247 DISALLOW_COPY_AND_ASSIGN(AddressList);
247 }; 248 };
248 249
249 250
250 class Socket { 251 // We write Sockets into the native field of the _NativeSocket object
252 // on the Dart side. They are allocated in SetSocketIdNativeField(), and are
253 // deallocated either from the finalizer attached to _NativeSockets there, or
254 // from the eventhandler, whichever drops the last reference.
255 class Socket : public ReferenceCounted<Socket> {
251 public: 256 public:
252 enum SocketRequest { 257 enum SocketRequest {
253 kLookupRequest = 0, 258 kLookupRequest = 0,
254 kListInterfacesRequest = 1, 259 kListInterfacesRequest = 1,
255 kReverseLookupRequest = 2, 260 kReverseLookupRequest = 2,
256 }; 261 };
257 262
263 explicit Socket(intptr_t fd);
264
265 intptr_t fd() const { return fd_; }
266 void SetClosedFd();
267
268 Dart_Port port() const { return port_; }
269 void set_port(Dart_Port port) { port_ = port; }
270
271 // TODO(dart:io): Convert these to instance methods where possible.
258 static bool Initialize(); 272 static bool Initialize();
259 static intptr_t Available(intptr_t fd); 273 static intptr_t Available(intptr_t fd);
260 static intptr_t Read(intptr_t fd, void* buffer, intptr_t num_bytes); 274 static intptr_t Read(intptr_t fd, void* buffer, intptr_t num_bytes);
261 static intptr_t Write(intptr_t fd, const void* buffer, intptr_t num_bytes); 275 static intptr_t Write(intptr_t fd, const void* buffer, intptr_t num_bytes);
262 // Send data on a socket. The port to send to is specified in the port 276 // Send data on a socket. The port to send to is specified in the port
263 // component of the passed RawAddr structure. The RawAddr structure is only 277 // component of the passed RawAddr structure. The RawAddr structure is only
264 // used for datagram sockets. 278 // used for datagram sockets.
265 static intptr_t SendTo(intptr_t fd, 279 static intptr_t SendTo(intptr_t fd,
266 const void* buffer, 280 const void* buffer,
267 intptr_t num_bytes, 281 intptr_t num_bytes,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 static AddressList<InterfaceSocketAddress>* ListInterfaces( 340 static AddressList<InterfaceSocketAddress>* ListInterfaces(
327 int type, 341 int type,
328 OSError** os_error); 342 OSError** os_error);
329 343
330 static CObject* LookupRequest(const CObjectArray& request); 344 static CObject* LookupRequest(const CObjectArray& request);
331 static CObject* ListInterfacesRequest(const CObjectArray& request); 345 static CObject* ListInterfacesRequest(const CObjectArray& request);
332 static CObject* ReverseLookupRequest(const CObjectArray& request); 346 static CObject* ReverseLookupRequest(const CObjectArray& request);
333 347
334 static Dart_Port GetServicePort(); 348 static Dart_Port GetServicePort();
335 349
336 static void SetSocketIdNativeField(Dart_Handle socket, intptr_t id); 350 static void SetSocketIdNativeField(Dart_Handle handle,
337 static intptr_t GetSocketIdNativeField(Dart_Handle socket); 351 intptr_t id,
352 bool listening);
353 static void ReuseSocketIdNativeField(Dart_Handle handle,
354 Socket* socket,
355 bool listening);
356 static Socket* GetSocketIdNativeField(Dart_Handle socket);
338 357
339 private: 358 private:
340 DISALLOW_ALLOCATION(); 359 ~Socket() { ASSERT(fd_ == kClosedFd); }
341 DISALLOW_IMPLICIT_CONSTRUCTORS(Socket); 360
361 static const int kClosedFd = -1;
362
363 intptr_t fd_;
364 Dart_Port port_;
365
366 friend class ReferenceCounted<Socket>;
367 DISALLOW_COPY_AND_ASSIGN(Socket);
342 }; 368 };
343 369
344 370
345 class ServerSocket { 371 class ServerSocket {
346 public: 372 public:
347 static const intptr_t kTemporaryFailure = -2; 373 static const intptr_t kTemporaryFailure = -2;
348 374
349 static intptr_t Accept(intptr_t fd); 375 static intptr_t Accept(intptr_t fd);
350 376
351 // Creates a socket which is bound and listens. The port to listen on is 377 // Creates a socket which is bound and listens. The port to listen on is
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 bool shared); 424 bool shared);
399 425
400 // This should be called from the event handler for every kCloseEvent it gets 426 // This should be called from the event handler for every kCloseEvent it gets
401 // on listening sockets. 427 // on listening sockets.
402 // 428 //
403 // Returns `true` if the last reference has been dropped and the underlying 429 // Returns `true` if the last reference has been dropped and the underlying
404 // socket can be closed. 430 // socket can be closed.
405 // 431 //
406 // The caller is responsible for obtaining the mutex first, before calling 432 // The caller is responsible for obtaining the mutex first, before calling
407 // this function. 433 // this function.
408 bool CloseSafe(intptr_t socketfd); 434 bool CloseSafe(Socket* socketfd);
409 435
410 Mutex* mutex() { return mutex_; } 436 Mutex* mutex() { return mutex_; }
411 437
412 private: 438 private:
413 struct OSSocket { 439 struct OSSocket {
414 RawAddr address; 440 RawAddr address;
415 int port; 441 int port;
416 bool v6_only; 442 bool v6_only;
417 bool shared; 443 bool shared;
418 int ref_count; 444 int ref_count;
419 intptr_t socketfd; 445 Socket* socketfd;
420 446
421 // Singly linked lists of OSSocket instances which listen on the same port 447 // Singly linked lists of OSSocket instances which listen on the same port
422 // but on different addresses. 448 // but on different addresses.
423 OSSocket* next; 449 OSSocket* next;
424 450
425 OSSocket(RawAddr address, 451 OSSocket(RawAddr address,
426 int port, 452 int port,
427 bool v6_only, 453 bool v6_only,
428 bool shared, 454 bool shared,
429 intptr_t socketfd) 455 Socket* socketfd)
430 : address(address), 456 : address(address),
431 port(port), 457 port(port),
432 v6_only(v6_only), 458 v6_only(v6_only),
433 shared(shared), 459 shared(shared),
434 ref_count(0), 460 ref_count(0),
435 socketfd(socketfd), 461 socketfd(socketfd),
436 next(NULL) {} 462 next(NULL) {}
437 }; 463 };
438 464
439 static const intptr_t kInitialSocketsCount = 8; 465 static const intptr_t kInitialSocketsCount = 8;
440 466
441 OSSocket* findOSSocketWithAddress(OSSocket* current, const RawAddr& addr) { 467 OSSocket* FindOSSocketWithAddress(OSSocket* current, const RawAddr& addr) {
442 while (current != NULL) { 468 while (current != NULL) {
443 if (SocketAddress::AreAddressesEqual(current->address, addr)) { 469 if (SocketAddress::AreAddressesEqual(current->address, addr)) {
444 return current; 470 return current;
445 } 471 }
446 current = current->next; 472 current = current->next;
447 } 473 }
448 return NULL; 474 return NULL;
449 } 475 }
450 476
451 static bool SameIntptrValue(void* key1, void* key2) { 477 static bool SameIntptrValue(void* key1, void* key2) {
452 return reinterpret_cast<intptr_t>(key1) == reinterpret_cast<intptr_t>(key2); 478 return reinterpret_cast<intptr_t>(key1) == reinterpret_cast<intptr_t>(key2);
453 } 479 }
454 480
455 static uint32_t GetHashmapHashFromIntptr(intptr_t i) { 481 static uint32_t GetHashmapHashFromIntptr(intptr_t i) {
456 return static_cast<uint32_t>((i + 1) & 0xFFFFFFFF); 482 return static_cast<uint32_t>((i + 1) & 0xFFFFFFFF);
457 } 483 }
458 484
459 485
460 static void* GetHashmapKeyFromIntptr(intptr_t i) { 486 static void* GetHashmapKeyFromIntptr(intptr_t i) {
461 return reinterpret_cast<void*>(i + 1); 487 return reinterpret_cast<void*>(i + 1);
462 } 488 }
463 489
464 OSSocket* LookupByPort(intptr_t port); 490 OSSocket* LookupByPort(intptr_t port);
465 void InsertByPort(intptr_t port, OSSocket* socket); 491 void InsertByPort(intptr_t port, OSSocket* socket);
466 void RemoveByPort(intptr_t port); 492 void RemoveByPort(intptr_t port);
467 493
468 OSSocket* LookupByFd(intptr_t fd); 494 OSSocket* LookupByFd(Socket* fd);
469 void InsertByFd(intptr_t fd, OSSocket* socket); 495 void InsertByFd(Socket* fd, OSSocket* socket);
470 void RemoveByFd(intptr_t fd); 496 void RemoveByFd(Socket* fd);
471 497
472 bool CloseOneSafe(OSSocket* os_socket, bool update_hash_maps); 498 bool CloseOneSafe(OSSocket* os_socket, bool update_hash_maps);
473 void CloseAllSafe(); 499 void CloseAllSafe();
474 500
475 HashMap sockets_by_port_; 501 HashMap sockets_by_port_;
476 HashMap sockets_by_fd_; 502 HashMap sockets_by_fd_;
477 503
478 Mutex* mutex_; 504 Mutex* mutex_;
479 505
480 DISALLOW_COPY_AND_ASSIGN(ListeningSocketRegistry); 506 DISALLOW_COPY_AND_ASSIGN(ListeningSocketRegistry);
481 }; 507 };
482 508
483 } // namespace bin 509 } // namespace bin
484 } // namespace dart 510 } // namespace dart
485 511
486 #endif // RUNTIME_BIN_SOCKET_H_ 512 #endif // RUNTIME_BIN_SOCKET_H_
OLDNEW
« no previous file with comments | « runtime/bin/reference_counting.h ('k') | runtime/bin/socket.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698