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

Side by Side Diff: third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp

Issue 2025783002: Worker: Introduce an observation mechanism for WorkerThread termination (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@delayed_task
Patch Set: Stop tracing CrossThread(Weak)Persistents Created 4 years, 6 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 m_bridge->disconnect(); 170 m_bridge->disconnect();
171 m_bridge.clear(); 171 m_bridge.clear();
172 } 172 }
173 173
174 DEFINE_TRACE(WorkerWebSocketChannel) 174 DEFINE_TRACE(WorkerWebSocketChannel)
175 { 175 {
176 visitor->trace(m_bridge); 176 visitor->trace(m_bridge);
177 WebSocketChannel::trace(visitor); 177 WebSocketChannel::trace(visitor);
178 } 178 }
179 179
180 Peer::Peer(Bridge* bridge, PassRefPtr<WorkerLoaderProxy> loaderProxy, WebSocketC hannelSyncHelper* syncHelper) 180 Peer::Peer(Bridge* bridge, PassRefPtr<WorkerLoaderProxy> loaderProxy, WebSocketC hannelSyncHelper* syncHelper, WorkerThreadContext* workerThreadContext)
181 : m_bridge(bridge) 181 : WorkerThreadLifecycleObserver(workerThreadContext)
182 , m_bridge(bridge)
182 , m_loaderProxy(loaderProxy) 183 , m_loaderProxy(loaderProxy)
183 , m_mainWebSocketChannel(nullptr) 184 , m_mainWebSocketChannel(nullptr)
184 , m_syncHelper(syncHelper) 185 , m_syncHelper(syncHelper)
185 { 186 {
186 ASSERT(!isMainThread()); 187 DCHECK(isMainThread());
187 } 188 }
188 189
189 Peer::~Peer() 190 Peer::~Peer()
190 { 191 {
191 ASSERT(!isMainThread()); 192 DCHECK(isMainThread());
192 } 193 }
193 194
194 void Peer::initialize(PassOwnPtr<SourceLocation> location, ExecutionContext* con text) 195 bool Peer::initialize(PassOwnPtr<SourceLocation> location, ExecutionContext* con text)
195 { 196 {
196 ASSERT(isMainThread()); 197 ASSERT(isMainThread());
198 if (wasContextDestroyedBeforeObserverCreation())
kinuko 2016/06/10 02:05:28 Yeah this feels weird. should just check lifecycle
199 return false;
197 Document* document = toDocument(context); 200 Document* document = toDocument(context);
198 m_mainWebSocketChannel = DocumentWebSocketChannel::create(document, this, st d::move(location)); 201 m_mainWebSocketChannel = DocumentWebSocketChannel::create(document, this, st d::move(location));
199 m_syncHelper->signalWorkerThread(); 202 return true;
200 } 203 }
201 204
202 void Peer::connect(const KURL& url, const String& protocol) 205 void Peer::connect(const KURL& url, const String& protocol)
203 { 206 {
204 ASSERT(isMainThread()); 207 ASSERT(isMainThread());
205 ASSERT(m_syncHelper); 208 ASSERT(m_syncHelper);
206 if (!m_mainWebSocketChannel) { 209 if (!m_mainWebSocketChannel) {
207 m_syncHelper->setConnectRequestResult(false); 210 m_syncHelper->setConnectRequestResult(false);
208 } else { 211 } else {
209 bool connectRequestResult = m_mainWebSocketChannel->connect(url, protoco l); 212 bool connectRequestResult = m_mainWebSocketChannel->connect(url, protoco l);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 if (bridge->client()) 353 if (bridge->client())
351 bridge->client()->didError(); 354 bridge->client()->didError();
352 } 355 }
353 356
354 void Peer::didError() 357 void Peer::didError()
355 { 358 {
356 ASSERT(isMainThread()); 359 ASSERT(isMainThread());
357 m_loaderProxy->postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlob alScopeDidError, m_bridge)); 360 m_loaderProxy->postTaskToWorkerGlobalScope(createCrossThreadTask(&workerGlob alScopeDidError, m_bridge));
358 } 361 }
359 362
363 void Peer::contextDestroyed()
364 {
365 DCHECK(isMainThread());
366 if (m_mainWebSocketChannel) {
367 m_mainWebSocketChannel->disconnect();
368 m_mainWebSocketChannel = nullptr;
369 }
370 m_bridge = nullptr;
371 }
372
360 DEFINE_TRACE(Peer) 373 DEFINE_TRACE(Peer)
361 { 374 {
362 visitor->trace(m_bridge);
363 visitor->trace(m_mainWebSocketChannel); 375 visitor->trace(m_mainWebSocketChannel);
364 visitor->trace(m_syncHelper); 376 visitor->trace(m_syncHelper);
365 WebSocketChannelClient::trace(visitor); 377 WebSocketChannelClient::trace(visitor);
378 WorkerThreadLifecycleObserver::trace(visitor);
366 } 379 }
367 380
368 Bridge::Bridge(WebSocketChannelClient* client, WorkerGlobalScope& workerGlobalSc ope) 381 Bridge::Bridge(WebSocketChannelClient* client, WorkerGlobalScope& workerGlobalSc ope)
369 : m_client(client) 382 : m_client(client)
370 , m_workerGlobalScope(workerGlobalScope) 383 , m_workerGlobalScope(workerGlobalScope)
371 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) 384 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy())
372 , m_syncHelper(WebSocketChannelSyncHelper::create(adoptPtr(new WaitableEvent ()))) 385 , m_syncHelper(WebSocketChannelSyncHelper::create(adoptPtr(new WaitableEvent ())))
373 , m_peer(new Peer(this, m_loaderProxy, m_syncHelper))
374 { 386 {
375 } 387 }
376 388
377 Bridge::~Bridge() 389 Bridge::~Bridge()
378 { 390 {
379 ASSERT(!m_peer); 391 ASSERT(!m_peer);
380 } 392 }
381 393
394 void Bridge::createPeerOnMainThread(PassOwnPtr<SourceLocation> location, WorkerT hreadContext* workerThreadContext, ExecutionContext* context)
395 {
396 DCHECK(isMainThread());
397 DCHECK(!m_peer);
398 Peer* peer = new Peer(this, m_loaderProxy, m_syncHelper, workerThreadContext );
399 if (peer->initialize(std::move(location), context))
400 m_peer = peer;
401 m_syncHelper->signalWorkerThread();
402 }
403
382 void Bridge::initialize(PassOwnPtr<SourceLocation> location) 404 void Bridge::initialize(PassOwnPtr<SourceLocation> location)
383 { 405 {
384 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::initialize, wrapCr ossThreadPersistent(m_peer.get()), passed(std::move(location))))) { 406 // Wait for completion of the task on the main thread because the connection
407 // must synchronously be established (see Bridge::connect).
408 if (!waitForMethodCompletion(createCrossThreadTask(&Bridge::createPeerOnMain Thread, wrapCrossThreadPersistent(this), passed(std::move(location)), wrapCrossT hreadPersistent(m_workerGlobalScope->thread()->workerThreadContext())))) {
385 // The worker thread has been signalled to shutdown before method comple tion. 409 // The worker thread has been signalled to shutdown before method comple tion.
386 disconnect(); 410 disconnect();
387 } 411 }
388 } 412 }
389 413
390 bool Bridge::connect(const KURL& url, const String& protocol) 414 bool Bridge::connect(const KURL& url, const String& protocol)
391 { 415 {
392 if (!m_peer) 416 if (!m_peer)
393 return false; 417 return false;
394 418
419 // Wait for completion of the task on the main thread because the mixed
420 // content check must synchronously be conducted.
395 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, wrapCross ThreadPersistent(m_peer.get()), url, protocol))) 421 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, wrapCross ThreadPersistent(m_peer.get()), url, protocol)))
396 return false; 422 return false;
397 423
398 return m_syncHelper->connectRequestResult(); 424 return m_syncHelper->connectRequestResult();
399 } 425 }
400 426
401 void Bridge::send(const CString& message) 427 void Bridge::send(const CString& message)
402 { 428 {
403 ASSERT(m_peer); 429 ASSERT(m_peer);
404 OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(message.length())); 430 OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(message.length()));
(...skipping 30 matching lines...) Expand all
435 { 461 {
436 ASSERT(m_peer); 462 ASSERT(m_peer);
437 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::fail, wrapCross ThreadPersistent(m_peer.get()), reason, level, passed(std::move(location)))); 463 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::fail, wrapCross ThreadPersistent(m_peer.get()), reason, level, passed(std::move(location))));
438 } 464 }
439 465
440 void Bridge::disconnect() 466 void Bridge::disconnect()
441 { 467 {
442 if (!m_peer) 468 if (!m_peer)
443 return; 469 return;
444 470
471 // Wait for completion of the task on the main thread to ensure that
472 // |m_peer| does not touch this Bridge object after this point.
445 waitForMethodCompletion(createCrossThreadTask(&Peer::disconnect, wrapCrossTh readPersistent(m_peer.get()))); 473 waitForMethodCompletion(createCrossThreadTask(&Peer::disconnect, wrapCrossTh readPersistent(m_peer.get())));
446 // Here |m_peer| is detached from the main thread and we can delete it.
447 474
448 m_client = nullptr; 475 m_client = nullptr;
449 m_peer = nullptr; 476 m_peer = nullptr;
450 m_syncHelper = nullptr; 477 m_syncHelper = nullptr;
451 // We won't use this any more. 478 // We won't use this any more.
452 m_workerGlobalScope.clear(); 479 m_workerGlobalScope.clear();
453 } 480 }
454 481
455 // Caller of this function should hold a reference to the bridge, because this f unction may call WebSocket::didClose() in the end, 482 // Caller of this function should hold a reference to the bridge, because this f unction may call WebSocket::didClose() in the end,
456 // which causes the bridge to get disconnected from the WebSocket and deleted if there is no other reference. 483 // which causes the bridge to get disconnected from the WebSocket and deleted if there is no other reference.
(...skipping 10 matching lines...) Expand all
467 m_syncHelper->wait(); 494 m_syncHelper->wait();
468 // This is checking whether a shutdown event is fired or not. 495 // This is checking whether a shutdown event is fired or not.
469 return !m_workerGlobalScope->thread()->terminated(); 496 return !m_workerGlobalScope->thread()->terminated();
470 } 497 }
471 498
472 DEFINE_TRACE(Bridge) 499 DEFINE_TRACE(Bridge)
473 { 500 {
474 visitor->trace(m_client); 501 visitor->trace(m_client);
475 visitor->trace(m_workerGlobalScope); 502 visitor->trace(m_workerGlobalScope);
476 visitor->trace(m_syncHelper); 503 visitor->trace(m_syncHelper);
477 visitor->trace(m_peer);
478 } 504 }
479 505
480 } // namespace blink 506 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698