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

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: remake and add tests 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 ASSERT(!isMainThread());
yhirano 2016/06/09 04:55:13 DCHECK(isMainThread())
nhiroki 2016/06/09 07:37:07 Done.
192 } 193 }
193 194
194 void Peer::initialize(PassOwnPtr<SourceLocation> location, ExecutionContext* con text) 195 void Peer::initialize(PassOwnPtr<SourceLocation> location, ExecutionContext* con text)
195 { 196 {
196 ASSERT(isMainThread()); 197 ASSERT(isMainThread());
197 Document* document = toDocument(context); 198 if (!wasContextDestroyedBeforeObserverCreation()) {
198 m_mainWebSocketChannel = DocumentWebSocketChannel::create(document, this, st d::move(location)); 199 Document* document = toDocument(context);
200 m_mainWebSocketChannel = DocumentWebSocketChannel::create(document, this , std::move(location));
201 }
199 m_syncHelper->signalWorkerThread(); 202 m_syncHelper->signalWorkerThread();
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 {
(...skipping 141 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 }
yhirano 2016/06/09 04:55:13 m_bridge = nullptr;
nhiroki 2016/06/09 07:37:07 Done.
370 }
371
360 DEFINE_TRACE(Peer) 372 DEFINE_TRACE(Peer)
361 { 373 {
362 visitor->trace(m_bridge); 374 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());
yhirano 2016/06/09 04:55:13 +DCHECK(!m_peer);
nhiroki 2016/06/09 07:37:07 Done.
397 m_peer = new Peer(this, m_loaderProxy, m_syncHelper, workerThreadContext);
398 m_peer->initialize(std::move(location), context);
yhirano 2016/06/09 04:55:13 [optional] Is it good to set |m_peer| only when ne
nhiroki 2016/06/09 07:37:06 Done.
399 }
400
382 void Bridge::initialize(PassOwnPtr<SourceLocation> location) 401 void Bridge::initialize(PassOwnPtr<SourceLocation> location)
383 { 402 {
384 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::initialize, wrapCr ossThreadPersistent(m_peer.get()), passed(std::move(location))))) { 403 // TODO(nhiroki): Stop waiting for completion of the task on the main
404 // thread and make this function async instead. This wait was necessary to
405 // prevent worker thread shutdown during initialization on the main thread.
406 // If it happens, the main thread may retain dangling pointers to objects on
407 // the worker thread. However, in the current implementation, the shutdown
408 // sequence always goes through the main thread and gives a chance to
409 // release pointers before they dangle. See Peer::contextDestroyed.
410 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. 411 // The worker thread has been signalled to shutdown before method comple tion.
386 disconnect(); 412 disconnect();
387 } 413 }
388 } 414 }
389 415
390 bool Bridge::connect(const KURL& url, const String& protocol) 416 bool Bridge::connect(const KURL& url, const String& protocol)
391 { 417 {
392 if (!m_peer) 418 if (!m_peer)
393 return false; 419 return false;
394 420
421 // Wait for completion of the task on the main thread because the mixed
422 // content check must synchronously be conducted.
395 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, wrapCross ThreadPersistent(m_peer.get()), url, protocol))) 423 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, wrapCross ThreadPersistent(m_peer.get()), url, protocol)))
396 return false; 424 return false;
397 425
398 return m_syncHelper->connectRequestResult(); 426 return m_syncHelper->connectRequestResult();
399 } 427 }
400 428
401 void Bridge::send(const CString& message) 429 void Bridge::send(const CString& message)
402 { 430 {
403 ASSERT(m_peer); 431 ASSERT(m_peer);
404 OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(message.length())); 432 OwnPtr<Vector<char>> data = adoptPtr(new Vector<char>(message.length()));
(...skipping 30 matching lines...) Expand all
435 { 463 {
436 ASSERT(m_peer); 464 ASSERT(m_peer);
437 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::fail, wrapCross ThreadPersistent(m_peer.get()), reason, level, passed(std::move(location)))); 465 m_loaderProxy->postTaskToLoader(createCrossThreadTask(&Peer::fail, wrapCross ThreadPersistent(m_peer.get()), reason, level, passed(std::move(location))));
438 } 466 }
439 467
440 void Bridge::disconnect() 468 void Bridge::disconnect()
441 { 469 {
442 if (!m_peer) 470 if (!m_peer)
443 return; 471 return;
444 472
473 // TODO(nhiroki): Stop waiting for completion of the task on the main thread
474 // and make this function async instead. See a comment on Bridge::initialize
475 // for more details.
445 waitForMethodCompletion(createCrossThreadTask(&Peer::disconnect, wrapCrossTh readPersistent(m_peer.get()))); 476 waitForMethodCompletion(createCrossThreadTask(&Peer::disconnect, wrapCrossTh readPersistent(m_peer.get())));
446 // Here |m_peer| is detached from the main thread and we can delete it. 477 // Here |m_peer| is detached from the main thread and we can delete it.
447 478
448 m_client = nullptr; 479 m_client = nullptr;
449 m_peer = nullptr; 480 m_peer = nullptr;
450 m_syncHelper = nullptr; 481 m_syncHelper = nullptr;
451 // We won't use this any more. 482 // We won't use this any more.
452 m_workerGlobalScope.clear(); 483 m_workerGlobalScope.clear();
453 } 484 }
454 485
(...skipping 16 matching lines...) Expand all
471 502
472 DEFINE_TRACE(Bridge) 503 DEFINE_TRACE(Bridge)
473 { 504 {
474 visitor->trace(m_client); 505 visitor->trace(m_client);
475 visitor->trace(m_workerGlobalScope); 506 visitor->trace(m_workerGlobalScope);
476 visitor->trace(m_syncHelper); 507 visitor->trace(m_syncHelper);
477 visitor->trace(m_peer); 508 visitor->trace(m_peer);
478 } 509 }
479 510
480 } // namespace blink 511 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698