Changeset 245802 in webkit


Ignore:
Timestamp:
May 27, 2019 5:10:41 PM (5 years ago)
Author:
commit-queue@webkit.org
Message:

[CURL] Fix crashing SocketStreamHandle.
https://bugs.webkit.org/show_bug.cgi?id=197873

Patch by Takashi Komori <Takashi.Komori@sony.com> on 2019-05-27
Reviewed by Fujii Hironori.

Source/WebCore:

When NetworkSocketStream was destructed SocketStreamHandleImple::platformClose was called wrongly times.
This is because closed state is not set.

Test: http/tests/websocket/tests/hybi/workers/close.html

  • platform/network/curl/SocketStreamHandleImpl.h:
  • platform/network/curl/SocketStreamHandleImplCurl.cpp:

(WebCore::SocketStreamHandleImpl::platformSendInternal):
(WebCore::SocketStreamHandleImpl::platformClose):
(WebCore::SocketStreamHandleImpl::threadEntryPoint):
(WebCore::SocketStreamHandleImpl::handleError):
(WebCore::SocketStreamHandleImpl::callOnWorkerThread):
(WebCore::SocketStreamHandleImpl::executeTasks):

LayoutTests:

  • platform/wincairo-wk1/TestExpectations:
  • platform/wincairo/TestExpectations:
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r245798 r245802  
     12019-05-27  Takashi Komori  <Takashi.Komori@sony.com>
     2
     3        [CURL] Fix crashing SocketStreamHandle.
     4        https://bugs.webkit.org/show_bug.cgi?id=197873
     5
     6        Reviewed by Fujii Hironori.
     7
     8        * platform/wincairo-wk1/TestExpectations:
     9        * platform/wincairo/TestExpectations:
     10
    1112019-05-27  Oriol Brufau  <obrufau@igalia.com>
    212
  • trunk/LayoutTests/platform/wincairo-wk1/TestExpectations

    r245321 r245802  
    294294# Failures on WebKit Legacy
    295295
     296webkit.org/b/89153 http/tests/websocket/tests/hybi/workers/close.html [ Pass Failure ]
     297
    296298# Cookie policy only supported in WK2.
    297299http/tests/cookies/only-accept-first-party-cookies.html [ Skip ]
  • trunk/LayoutTests/platform/wincairo/TestExpectations

    r245733 r245802  
    977977http/tests/websocket/tests/hybi/websocket-blocked-from-setting-cookie-as-third-party.html [ Pass Failure ]
    978978http/tests/websocket/tests/hybi/websocket-cookie-overwrite-behavior.html [ Pass Failure ]
    979 http/tests/websocket/tests/hybi/workers/close.html [ Pass Failure ]
    980979http/tests/websocket/tests/hybi/workers/worker-reload.html [ Timeout Pass ]
    981980
  • trunk/Source/WebCore/ChangeLog

    r245798 r245802  
     12019-05-27  Takashi Komori  <Takashi.Komori@sony.com>
     2
     3        [CURL] Fix crashing SocketStreamHandle.
     4        https://bugs.webkit.org/show_bug.cgi?id=197873
     5
     6        Reviewed by Fujii Hironori.
     7
     8        When NetworkSocketStream was destructed SocketStreamHandleImple::platformClose was called wrongly times.
     9        This is because closed state is not set.
     10
     11        Test: http/tests/websocket/tests/hybi/workers/close.html
     12
     13        * platform/network/curl/SocketStreamHandleImpl.h:
     14        * platform/network/curl/SocketStreamHandleImplCurl.cpp:
     15        (WebCore::SocketStreamHandleImpl::platformSendInternal):
     16        (WebCore::SocketStreamHandleImpl::platformClose):
     17        (WebCore::SocketStreamHandleImpl::threadEntryPoint):
     18        (WebCore::SocketStreamHandleImpl::handleError):
     19        (WebCore::SocketStreamHandleImpl::callOnWorkerThread):
     20        (WebCore::SocketStreamHandleImpl::executeTasks):
     21
    1222019-05-27  Oriol Brufau  <obrufau@igalia.com>
    223
  • trunk/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h

    r240117 r245802  
    3535#include "SocketStreamHandle.h"
    3636#include <pal/SessionID.h>
     37#include <wtf/Function.h>
    3738#include <wtf/Lock.h>
     39#include <wtf/MessageQueue.h>
    3840#include <wtf/RefCounted.h>
    39 #include <wtf/Seconds.h>
    4041#include <wtf/StreamBuffer.h>
    4142#include <wtf/Threading.h>
     
    6869    void stopThread();
    6970
    70     static const size_t kWriteBufferSize = 4 * 1024;
     71    void callOnWorkerThread(Function<void()>&&);
     72    void executeTasks();
     73
    7174    static const size_t kReadBufferSize = 4 * 1024;
    7275
     
    7578    std::atomic<bool> m_running { true };
    7679
    77     std::atomic<size_t> m_writeBufferSize { 0 };
    78     size_t m_writeBufferOffset;
     80    MessageQueue<Function<void()>> m_taskQueue;
     81
     82    bool m_hasPendingWriteData { false };
     83    size_t m_writeBufferSize { 0 };
     84    size_t m_writeBufferOffset { 0 };
    7985    UniqueArray<uint8_t> m_writeBuffer;
    8086
  • trunk/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp

    r240121 r245802  
    4141#include "SocketStreamHandleClient.h"
    4242#include "StorageSessionProvider.h"
    43 #include <wtf/Lock.h>
    4443#include <wtf/MainThread.h>
    4544#include <wtf/URL.h>
     
    7574    ASSERT(isMainThread());
    7675
    77     // If there's data waiting, return zero to indicate whole data should be put in a m_buffer.
    78     // This is thread-safe because state is read in atomic. Also even if the state is cleared by
    79     // worker thread between load() and evaluation of size, it is okay because invocation of
    80     // sendPendingData() is serialized in the main thread, so that another call will be happen
    81     // immediately.
    82     if (m_writeBufferSize.load())
     76    if (m_hasPendingWriteData)
    8377        return 0;
    8478
    85     if (length > kWriteBufferSize)
    86         length = kWriteBufferSize;
    87 
    88     // We copy the buffer and then set the state atomically to say there are bytes available.
    89     // The worker thread will skip reading the buffer if no bytes are available, so it won't
    90     // access the buffer prematurely
    91     m_writeBuffer = makeUniqueArray<uint8_t>(length);
    92     memcpy(m_writeBuffer.get(), data, length);
    93     m_writeBufferOffset = 0;
    94     m_writeBufferSize.store(length);
     79    m_hasPendingWriteData = true;
     80
     81    auto writeBuffer = makeUniqueArray<uint8_t>(length);
     82    memcpy(writeBuffer.get(), data, length);
     83
     84    callOnWorkerThread([this, writeBuffer = WTFMove(writeBuffer), writeBufferSize = length]() mutable {
     85        ASSERT(!isMainThread());
     86        m_writeBuffer = WTFMove(writeBuffer);
     87        m_writeBufferSize = writeBufferSize;
     88        m_writeBufferOffset = 0;
     89    });
    9590
    9691    return length;
     
    10499    if (m_state == Closed)
    105100        return;
     101    m_state = Closed;
    106102
    107103    stopThread();
     
    113109    ASSERT(!isMainThread());
    114110
    115     CurlSocketHandle socket { m_url, [this](CURLcode errorCode) {
     111    CurlSocketHandle socket { m_url.isolatedCopy(), [this](CURLcode errorCode) {
    116112        handleError(errorCode);
    117113    }};
     
    129125
    130126    while (m_running) {
    131         auto writeBufferSize = m_writeBufferSize.load();
    132         auto result = socket.wait(20_ms, writeBufferSize > 0);
     127        executeTasks();
     128
     129        auto result = socket.wait(20_ms, m_writeBuffer.get());
    133130        if (!result)
    134131            continue;
    135132
    136         // These logic only run when there's data waiting. In that case, m_writeBufferSize won't
    137         // updated by `platformSendInternal()` running in main thread.
     133        // These logic only run when there's data waiting.
    138134        if (result->writable && m_running) {
    139             auto offset = m_writeBufferOffset;
    140             auto bytesSent = socket.send(m_writeBuffer.get() + offset, writeBufferSize - offset);
    141             offset += bytesSent;
    142 
    143             if (writeBufferSize > offset)
    144                 m_writeBufferOffset = offset;
    145             else {
     135            auto bytesSent = socket.send(m_writeBuffer.get() + m_writeBufferOffset, m_writeBufferSize - m_writeBufferOffset);
     136            m_writeBufferOffset += bytesSent;
     137
     138            if (m_writeBufferSize <= m_writeBufferOffset) {
    146139                m_writeBuffer = nullptr;
     140                m_writeBufferSize = 0;
    147141                m_writeBufferOffset = 0;
    148                 m_writeBufferSize.store(0);
     142
    149143                callOnMainThread([this, protectedThis = makeRef(*this)] {
     144                    m_hasPendingWriteData = false;
    150145                    sendPendingData();
    151146                });
     
    175170        }
    176171    }
     172
     173    m_writeBuffer = nullptr;
    177174}
    178175
     
    180177{
    181178    m_running = false;
    182     callOnMainThread([this, protectedThis = makeRef(*this), errorCode, localizedDescription = CurlHandle::errorDescription(errorCode)] {
     179    callOnMainThread([this, protectedThis = makeRef(*this), errorCode, localizedDescription = CurlHandle::errorDescription(errorCode).isolatedCopy()] {
     180        if (m_state == Closed)
     181            return;
     182
    183183        if (errorCode == CURLE_RECV_ERROR)
    184184            m_client.didFailToReceiveSocketStreamData(*this);
     
    200200}
    201201
     202void SocketStreamHandleImpl::callOnWorkerThread(Function<void()>&& task)
     203{
     204    ASSERT(isMainThread());
     205    m_taskQueue.append(std::make_unique<Function<void()>>(WTFMove(task)));
     206}
     207
     208void SocketStreamHandleImpl::executeTasks()
     209{
     210    ASSERT(!isMainThread());
     211
     212    auto tasks = m_taskQueue.takeAllMessages();
     213    for (auto& task : tasks)
     214        (*task)();
     215}
     216
    202217} // namespace WebCore
    203218
Note: See TracChangeset for help on using the changeset viewer.