Fix using wxHTTP and wxFTP from worker thread in Unix ports.
This backportse18c8fd29a
,d421373c2e
and6c43aa90b6
from master to avoid crashes when using wxHTTP or wxFTP from threads other than main. See #17031.
This commit is contained in:
@@ -608,6 +608,7 @@ wxGTK:
|
|||||||
- Fix crashes in wxGTK3 when running with non-X11 backend (Marco Trevisan).
|
- Fix crashes in wxGTK3 when running with non-X11 backend (Marco Trevisan).
|
||||||
- Fix coordinates of wxSetCursorEvent propagated to parent windows.
|
- Fix coordinates of wxSetCursorEvent propagated to parent windows.
|
||||||
- Fix GTK+ warnings when refreshing wxListCtrl items (Scott Talbert).
|
- Fix GTK+ warnings when refreshing wxListCtrl items (Scott Talbert).
|
||||||
|
- Fix using wxHTTP and wxFTP from worker thread.
|
||||||
|
|
||||||
wxMSW:
|
wxMSW:
|
||||||
|
|
||||||
@@ -632,6 +633,7 @@ wxOSX:
|
|||||||
|
|
||||||
- Compilation fix for wxWebView under 10.10.
|
- Compilation fix for wxWebView under 10.10.
|
||||||
- Fix conversion of wxBitmap to wxImage in 64 bit builds.
|
- Fix conversion of wxBitmap to wxImage in 64 bit builds.
|
||||||
|
- Fix using wxHTTP and wxFTP from worker thread.
|
||||||
- Fix wxFileDialog::GetFilterIndex() for file open dialogs (phsilva).
|
- Fix wxFileDialog::GetFilterIndex() for file open dialogs (phsilva).
|
||||||
- Fix custom paper support (tijsv).
|
- Fix custom paper support (tijsv).
|
||||||
|
|
||||||
|
@@ -308,6 +308,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
wxSocketImpl(wxSocketBase& wxsocket);
|
wxSocketImpl(wxSocketBase& wxsocket);
|
||||||
|
|
||||||
|
// get the associated socket flags
|
||||||
|
wxSocketFlags GetSocketFlags() const { return m_wxsocket->GetFlags(); }
|
||||||
|
|
||||||
// true if we're a listening stream socket
|
// true if we're a listening stream socket
|
||||||
bool m_server;
|
bool m_server;
|
||||||
|
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include "wx/socket.h"
|
#include "wx/socket.h"
|
||||||
#include "wx/url.h"
|
#include "wx/url.h"
|
||||||
#include "wx/sstream.h"
|
#include "wx/sstream.h"
|
||||||
|
#include "wx/thread.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -575,23 +576,13 @@ void MyFrame::OnDatagram(wxCommandEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
#if wxUSE_URL
|
#if wxUSE_URL
|
||||||
|
|
||||||
void MyFrame::OnTestURL(wxCommandEvent& WXUNUSED(event))
|
void DoDownload(const wxString& urlname)
|
||||||
{
|
{
|
||||||
// Ask for the URL
|
wxString testname("URL");
|
||||||
static wxString s_urlname("http://www.google.com/");
|
if ( !wxIsMainThread() )
|
||||||
wxString urlname = wxGetTextFromUser
|
testname += " in worker thread";
|
||||||
(
|
|
||||||
_("Enter an URL to get"),
|
|
||||||
_("URL:"),
|
|
||||||
s_urlname
|
|
||||||
);
|
|
||||||
if ( urlname.empty() )
|
|
||||||
return; // cancelled by user
|
|
||||||
|
|
||||||
s_urlname = urlname;
|
TestLogger logtest(testname);
|
||||||
|
|
||||||
|
|
||||||
TestLogger logtest("URL");
|
|
||||||
|
|
||||||
// Parse the URL
|
// Parse the URL
|
||||||
wxURL url(urlname);
|
wxURL url(urlname);
|
||||||
@@ -626,6 +617,51 @@ void MyFrame::OnTestURL(wxCommandEvent& WXUNUSED(event))
|
|||||||
urlname, sout.GetString());
|
urlname, sout.GetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyFrame::OnTestURL(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
// Ask for the URL
|
||||||
|
static wxString s_urlname("http://www.google.com/");
|
||||||
|
wxString urlname = wxGetTextFromUser
|
||||||
|
(
|
||||||
|
_("Enter an URL to get"),
|
||||||
|
_("URL:"),
|
||||||
|
s_urlname
|
||||||
|
);
|
||||||
|
if ( urlname.empty() )
|
||||||
|
return; // cancelled by user
|
||||||
|
|
||||||
|
s_urlname = urlname;
|
||||||
|
|
||||||
|
// First do it in this thread.
|
||||||
|
DoDownload(urlname);
|
||||||
|
|
||||||
|
// And then also in a worker thread.
|
||||||
|
#if wxUSE_THREADS
|
||||||
|
class DownloadThread : public wxThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit DownloadThread(const wxString& url): m_url(url)
|
||||||
|
{
|
||||||
|
Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* Entry() wxOVERRIDE
|
||||||
|
{
|
||||||
|
DoDownload(m_url);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const wxString m_url;
|
||||||
|
};
|
||||||
|
|
||||||
|
// NB: there is a race condition here, we don't check for this thread
|
||||||
|
// termination before exiting the application, don't do this in real code!
|
||||||
|
new DownloadThread(urlname);
|
||||||
|
#endif // wxUSE_THREADS
|
||||||
|
}
|
||||||
|
|
||||||
#endif // wxUSE_URL
|
#endif // wxUSE_URL
|
||||||
|
|
||||||
void MyFrame::OnSocketEvent(wxSocketEvent& event)
|
void MyFrame::OnSocketEvent(wxSocketEvent& event)
|
||||||
|
@@ -79,8 +79,6 @@ wxFTP::wxFTP()
|
|||||||
m_username = wxT("anonymous");
|
m_username = wxT("anonymous");
|
||||||
m_password << wxGetUserId() << wxT('@') << wxGetFullHostName();
|
m_password << wxGetUserId() << wxT('@') << wxGetFullHostName();
|
||||||
|
|
||||||
SetNotify(0);
|
|
||||||
SetFlags(wxSOCKET_NOWAIT);
|
|
||||||
m_bPassive = true;
|
m_bPassive = true;
|
||||||
m_bEncounteredError = false;
|
m_bEncounteredError = false;
|
||||||
}
|
}
|
||||||
@@ -782,8 +780,6 @@ wxInputStream *wxFTP::GetInputStream(const wxString& path)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sock->SetFlags(wxSOCKET_WAITALL);
|
|
||||||
|
|
||||||
m_streaming = true;
|
m_streaming = true;
|
||||||
|
|
||||||
wxInputFTPStream *in_stream = new wxInputFTPStream(this, sock);
|
wxInputFTPStream *in_stream = new wxInputFTPStream(this, sock);
|
||||||
|
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include "wx/string.h"
|
#include "wx/string.h"
|
||||||
#include "wx/app.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "wx/tokenzr.h"
|
#include "wx/tokenzr.h"
|
||||||
@@ -48,8 +47,6 @@ wxHTTP::wxHTTP()
|
|||||||
m_read = false;
|
m_read = false;
|
||||||
m_proxy_mode = false;
|
m_proxy_mode = false;
|
||||||
m_http_response = 0;
|
m_http_response = 0;
|
||||||
|
|
||||||
SetNotify(wxSOCKET_LOST_FLAG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxHTTP::~wxHTTP()
|
wxHTTP::~wxHTTP()
|
||||||
@@ -370,16 +367,6 @@ bool wxHTTP::BuildRequest(const wxString& path, const wxString& method)
|
|||||||
SetHeader(wxT("Authorization"), GenerateAuthString(m_username, m_password));
|
SetHeader(wxT("Authorization"), GenerateAuthString(m_username, m_password));
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveState();
|
|
||||||
|
|
||||||
// we may use non blocking sockets only if we can dispatch events from them
|
|
||||||
int flags = wxIsMainThread() && wxApp::IsMainLoopRunning() ? wxSOCKET_NONE
|
|
||||||
: wxSOCKET_BLOCK;
|
|
||||||
// and we must use wxSOCKET_WAITALL to ensure that all data is sent
|
|
||||||
flags |= wxSOCKET_WAITALL;
|
|
||||||
SetFlags(flags);
|
|
||||||
Notify(false);
|
|
||||||
|
|
||||||
wxString buf;
|
wxString buf;
|
||||||
buf.Printf(wxT("%s %s HTTP/1.0\r\n"), method, path);
|
buf.Printf(wxT("%s %s HTTP/1.0\r\n"), method, path);
|
||||||
const wxWX2MBbuf pathbuf = buf.mb_str();
|
const wxWX2MBbuf pathbuf = buf.mb_str();
|
||||||
@@ -395,10 +382,8 @@ bool wxHTTP::BuildRequest(const wxString& path, const wxString& method)
|
|||||||
|
|
||||||
wxString tmp_str;
|
wxString tmp_str;
|
||||||
m_lastError = ReadLine(this, tmp_str);
|
m_lastError = ReadLine(this, tmp_str);
|
||||||
if (m_lastError != wxPROTO_NOERR) {
|
if (m_lastError != wxPROTO_NOERR)
|
||||||
RestoreState();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!tmp_str.Contains(wxT("HTTP/"))) {
|
if (!tmp_str.Contains(wxT("HTTP/"))) {
|
||||||
// TODO: support HTTP v0.9 which can have no header.
|
// TODO: support HTTP v0.9 which can have no header.
|
||||||
@@ -441,7 +426,7 @@ bool wxHTTP::BuildRequest(const wxString& path, const wxString& method)
|
|||||||
|
|
||||||
m_lastError = wxPROTO_NOERR;
|
m_lastError = wxPROTO_NOERR;
|
||||||
ret_value = ParseHeaders();
|
ret_value = ParseHeaders();
|
||||||
RestoreState();
|
|
||||||
return ret_value;
|
return ret_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,9 +525,6 @@ wxInputStream *wxHTTP::GetInputStream(const wxString& path)
|
|||||||
|
|
||||||
inp_stream->m_read_bytes = 0;
|
inp_stream->m_read_bytes = 0;
|
||||||
|
|
||||||
Notify(false);
|
|
||||||
SetFlags(wxSOCKET_BLOCK | wxSOCKET_WAITALL);
|
|
||||||
|
|
||||||
// no error; reset m_lastError
|
// no error; reset m_lastError
|
||||||
m_lastError = wxPROTO_NOERR;
|
m_lastError = wxPROTO_NOERR;
|
||||||
return inp_stream;
|
return inp_stream;
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#include "wx/protocol/log.h"
|
#include "wx/protocol/log.h"
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
|
#include "wx/app.h"
|
||||||
#include "wx/module.h"
|
#include "wx/module.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -63,7 +64,10 @@ IMPLEMENT_ABSTRACT_CLASS(wxProtocol, wxObject)
|
|||||||
|
|
||||||
wxProtocol::wxProtocol()
|
wxProtocol::wxProtocol()
|
||||||
#if wxUSE_SOCKETS
|
#if wxUSE_SOCKETS
|
||||||
: wxSocketClient()
|
// Only use non blocking sockets if we can dispatch events.
|
||||||
|
: wxSocketClient((wxIsMainThread() && wxApp::IsMainLoopRunning()
|
||||||
|
? wxSOCKET_NONE
|
||||||
|
: wxSOCKET_BLOCK) | wxSOCKET_WAITALL)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
m_lastError = wxPROTO_NOERR;
|
m_lastError = wxPROTO_NOERR;
|
||||||
|
@@ -98,6 +98,11 @@ wxSocketError wxSocketImplUnix::GetLastError() const
|
|||||||
|
|
||||||
void wxSocketImplUnix::DoEnableEvents(int flags, bool enable)
|
void wxSocketImplUnix::DoEnableEvents(int flags, bool enable)
|
||||||
{
|
{
|
||||||
|
// No events for blocking sockets, they should be usable from the other
|
||||||
|
// threads and the events only work for the sockets used by the main one.
|
||||||
|
if ( GetSocketFlags() & wxSOCKET_BLOCK )
|
||||||
|
return;
|
||||||
|
|
||||||
wxSocketManager * const manager = wxSocketManager::Get();
|
wxSocketManager * const manager = wxSocketManager::Get();
|
||||||
if (!manager)
|
if (!manager)
|
||||||
return;
|
return;
|
||||||
|
Reference in New Issue
Block a user