simgear/io/HTTPFileRequest.*: Use fnptr rather than std::function to avoid SEGVs with g++ on Linux.

Previous code sometimes gave a SEGV in _callback's destructor when
setCallback() was called; this is on Linux with g++-8.3.0. Have tried various
alternative ways to initialise _callback but the problem persistend.

So have switched to an old-style function-pointer plus void* approach.
This commit is contained in:
Julian Smith 2021-02-18 23:12:01 +00:00
parent f9ecf455ba
commit 97828a8e4e
2 changed files with 17 additions and 9 deletions

View File

@ -26,13 +26,13 @@ namespace simgear
{
namespace HTTP
{
//----------------------------------------------------------------------------
FileRequest::FileRequest(const std::string& url, const std::string& path, bool append):
Request(url, "GET"),
_filename(path),
_append(append),
_callback()
_callback(nullptr),
_callback_ref(nullptr)
{
if (append && _filename.isFile()) {
size_t size = _filename.sizeInBytes();
@ -45,9 +45,10 @@ namespace HTTP
}
}
void FileRequest::setCallback(std::function<void(const void* data, size_t numbytes)> callback)
void FileRequest::setCallback(Callback callback, void* ref)
{
_callback = callback;
_callback_ref = ref;
}
//----------------------------------------------------------------------------
@ -115,7 +116,7 @@ namespace HTTP
_file.write(s, n);
if (_callback) {
_callback(s, n);
_callback(_callback_ref, s, n);
}
}
@ -124,7 +125,7 @@ namespace HTTP
{
_file.close();
if (_callback) {
_callback(nullptr, 0);
_callback(_callback_ref, nullptr, 0);
}
}

View File

@ -53,16 +53,23 @@ namespace HTTP
FileRequest(const std::string& url, const std::string& path, bool append=false);
/*
* Set callback for each chunk of data we receive. Called with (nullptr,
* 0) when download has completed (successfully or unsuccesfully).
* Function pointer type for use with setCallback().
*/
void setCallback(std::function<void (const void* data, size_t numbytes)> callback);
typedef void (*Callback)(void* ref, const void* data, size_t numbytes);
/*
* Set callback for each chunk of data we receive. Called with
* (ref, nullptr, 0) when download has completed (successfully or
* unsuccesfully).
*/
void setCallback(Callback callback, void* ref);
protected:
SGPath _filename;
sg_ofstream _file;
bool _append;
std::function<void(const void* data, size_t numbytes)> _callback;
Callback _callback;
void* _callback_ref;
virtual void responseHeadersComplete();
virtual void gotBodyData(const char* s, int n);