diff options
author | Robert C. Helling <helling@atdotde.de> | 2016-03-16 00:29:28 +0100 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2016-03-15 22:38:47 -0700 |
commit | 2639281354445f0e37b5dd2e6927155361aaf792 (patch) | |
tree | e7f32a03449941d9789d669760d4b327eeb99ad7 | |
parent | 2368f3371bbdb587888d5f04095623c7b8b2ac2e (diff) | |
download | subsurface-2639281354445f0e37b5dd2e6927155361aaf792.tar.gz |
Copy picture struct for worker thread
This copies the picture struct when delegating image handling
to a worker thread to prevent a crashe when main thread
frees the picture upon selecting a different dive.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r-- | dive.c | 16 | ||||
-rw-r--r-- | dive.h | 2 | ||||
-rw-r--r-- | qt-ui/divepicturewidget.cpp | 13 | ||||
-rw-r--r-- | qt-ui/divepicturewidget.h | 1 | ||||
-rw-r--r-- | qthelper.cpp | 12 |
5 files changed, 36 insertions, 8 deletions
@@ -2357,6 +2357,20 @@ static void free_pic(struct picture *picture) } } +// When handling pictures in different threads, we need to copy them so we don't +// run into problems when the main thread frees the picture. + +struct picture *clone_picture(struct picture *src) +{ + struct picture *dst; + + dst = alloc_picture(); + copy_pl(src, dst); + return dst; +} + + + static int same_sample(struct sample *a, struct sample *b) { if (a->time.seconds != b->time.seconds) @@ -3387,7 +3401,7 @@ void dive_set_geodata_from_picture(struct dive *dive, struct picture *picture) } } -static void picture_free(struct picture *picture) +void picture_free(struct picture *picture) { if (!picture) return; @@ -376,6 +376,7 @@ struct picture { for (struct picture *picture = (_divestruct).picture_list; picture; picture = picture->next) extern struct picture *alloc_picture(); +extern struct picture *clone_picture(struct picture *src); extern bool dive_check_picture_time(struct dive *d, int shift_time, timestamp_t timestamp); extern void dive_create_picture(struct dive *d, char *filename, int shift_time, bool match_all); extern void dive_add_picture(struct dive *d, struct picture *newpic); @@ -385,6 +386,7 @@ extern bool picture_check_valid(char *filename, int shift_time); extern void picture_load_exif_data(struct picture *p); extern timestamp_t picture_get_timestamp(char *filename); extern void dive_set_geodata_from_picture(struct dive *d, struct picture *pic); +extern void picture_free(struct picture *picture); extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc); extern int get_depth_at_time(struct divecomputer *dc, int time); diff --git a/qt-ui/divepicturewidget.cpp b/qt-ui/divepicturewidget.cpp index bed3d3bd1..5e3711044 100644 --- a/qt-ui/divepicturewidget.cpp +++ b/qt-ui/divepicturewidget.cpp @@ -23,16 +23,17 @@ void loadPicture(struct picture *picture) SHashedImage::SHashedImage(struct picture *picture) : QImage() { - QUrl url = QUrl::fromUserInput(QString(picture->filename)); + QUrl url = QUrl::fromUserInput(localFilePath(QString(picture->filename))); + if(url.isLocalFile()) load(url.toLocalFile()); if (isNull()) { // Hash lookup. load(fileFromHash(picture->hash)); if (!isNull()) { - QtConcurrent::run(updateHash, picture); + QtConcurrent::run(updateHash, clone_picture(picture)); } else { - QtConcurrent::run(loadPicture, picture); + QtConcurrent::run(loadPicture, clone_picture(picture)); } } else { QByteArray hash = hashFile(url.toLocalFile()); @@ -46,6 +47,11 @@ ImageDownloader::ImageDownloader(struct picture *pic) picture = pic; } +ImageDownloader::~ImageDownloader() +{ + picture_free(picture); +} + void ImageDownloader::load(){ QUrl url = QUrl::fromUserInput(QString(picture->filename)); if (url.isValid()) { @@ -64,6 +70,7 @@ void ImageDownloader::load(){ void ImageDownloader::saveImage(QNetworkReply *reply) { QByteArray imageData = reply->readAll(); + qDebug() << "downloaded "; QImage image = QImage(); image.loadFromData(imageData); if (image.isNull()) diff --git a/qt-ui/divepicturewidget.h b/qt-ui/divepicturewidget.h index 54f5bb826..ff1240ed8 100644 --- a/qt-ui/divepicturewidget.h +++ b/qt-ui/divepicturewidget.h @@ -11,6 +11,7 @@ class ImageDownloader : public QObject { Q_OBJECT; public: ImageDownloader(struct picture *picture); + ~ImageDownloader(); void load(); private: struct picture *picture; diff --git a/qthelper.cpp b/qthelper.cpp index 67ce5daff..745fc5f60 100644 --- a/qthelper.cpp +++ b/qthelper.cpp @@ -1182,9 +1182,11 @@ void learnHash(struct picture *picture, QByteArray hash) QString localFilePath(const QString originalFilename) { - if (hashOf.contains(originalFilename) && localFilenameOf.contains(hashOf[originalFilename])) - return localFilenameOf[hashOf[originalFilename]]; - else + if (hashOf.contains(originalFilename)) + if (localFilenameOf.contains(hashOf[originalFilename])) + if (localFilenameOf[hashOf[originalFilename]] != "") + return localFilenameOf[hashOf[originalFilename]]; + return originalFilename; } @@ -1200,6 +1202,7 @@ void updateHash(struct picture *picture) { char *old = picture->hash; picture->hash = strdup(hash.toHex()); free(old); + picture_free(picture); } void hashPicture(struct picture *picture) @@ -1209,13 +1212,14 @@ void hashPicture(struct picture *picture) if (!same_string(picture->hash, "") && !same_string(picture->hash, oldHash)) mark_divelist_changed((true)); free(oldHash); + picture_free(picture); } extern "C" void cache_picture(struct picture *picture) { QString filename = picture->filename; if (!hashOf.contains(filename)) - QtConcurrent::run(hashPicture, picture); + QtConcurrent::run(hashPicture, clone_picture(picture)); } void learnImages(const QDir dir, int max_recursions, bool recursed) |