The attached patch fixes the issue here. I will release a v2.0.5 just for this fix (as it is critical) today, so no need to patch your package.
On Thu, Dec 31, 2009 at 4:52 PM, Chris <ch...@qbittorrent.org> wrote: > No need to test the patch, it does not fix the issue. I can reproduce it > now thanks to a torrent that a user sent me. The crash occurs when > displaying the main properties panel (especially pieces > downloaded/availability bars) for big torrents (e.g. 8GB crashes here). > > This causes a crash in Qt when trying to allocate a pixmap with 1px width > per piece (35762 pieces in my torrent). I will try to find a solution soon > (probably scale down the information before creating the pixmap). > > On Thu, Dec 31, 2009 at 4:09 PM, Chris <ch...@qbittorrent.org> wrote: > >> Could anybody try this patch and tell me if it fixes the issue (I cannot >> reproduce myself but I may have found a possible cause for this)? >> >> >> On Thu, Dec 31, 2009 at 3:49 PM, Chris <ch...@qbittorrent.org> wrote: >> >>> The backtrace looks the same as in : >>> https://bugs.launchpad.net/debian/+source/qbittorrent/+bug/501058 >>> >>> >>> On Thu, Dec 31, 2009 at 3:27 PM, Chris <ch...@qbittorrent.org> wrote: >>> >>>> It may also be useful the install libqt4-dbg (and get another backtrace) >>>> since the error seems to be in Qt4 (when drawing the pieces downloaded bar >>>> in the main properties panel). >>>> >>>> Best regards, >>>> Chris. >>>> >>>> >>>> On Thu, Dec 31, 2009 at 3:21 PM, Chris <ch...@qbittorrent.org> wrote: >>>> >>>>> I may have an idea. Does it still crash when the lower properties panel >>>>> is hidden? Click on the button corresponding to the currently displayed >>>>> tab >>>>> to hide it. >>>>> When hidden, qBittorrent no longer refreshes the panel information and >>>>> the bug might be in that code. >>>>> >>>> >>>> >>> >> >
Index: src/pieceavailabilitybar.h =================================================================== --- src/pieceavailabilitybar.h (revision 3245) +++ src/pieceavailabilitybar.h (revision 3248) @@ -36,6 +36,7 @@ #include <QPixmap> #include <QColor> #include <numeric> +#include <math.h> #define BAR_HEIGHT 18 @@ -54,20 +55,43 @@ double average = 0; if(avail.empty()) { // Empty bar - pixmap = QPixmap(1, 1); - QPainter painter(&pixmap); - painter.setPen(Qt::white); - painter.drawPoint(0,0); + QPixmap pix = QPixmap(1, 1); + pix.fill(); + pixmap = pix; } else { // Look for maximum value - average = std::accumulate(avail.begin(), avail.end(), 0)/(double)avail.size(); - uint nb_pieces = avail.size(); - pixmap = QPixmap(nb_pieces, 1); - QPainter painter(&pixmap); - std::vector<int>::iterator it; - for(uint i=0; i < nb_pieces; ++i) { - painter.setPen(getPieceColor(avail[i], average)); - painter.drawPoint(i,0); + int nb_pieces = avail.size(); + average = std::accumulate(avail.begin(), avail.end(), 0)/(double)nb_pieces; + // Reduce the number of pieces before creating the pixmap + // otherwise it can crash when there are too many pieces + if(nb_pieces > width()) { + int ratio = floor(nb_pieces/(double)width()); + std::vector<int> scaled_avail; + for(int i=0; i<nb_pieces; i+= ratio) { + int j = i; + int sum = avail[i]; + for(j=i+1; j<qMin(i+ratio, nb_pieces); ++j) { + sum += avail[j]; + } + scaled_avail.push_back(sum/(qMin(ratio, nb_pieces-i))); + } + QPixmap pix = QPixmap(scaled_avail.size(), 1); + pix.fill(); + QPainter painter(&pix); + for(qulonglong i=0; i < scaled_avail.size(); ++i) { + painter.setPen(getPieceColor(scaled_avail[i], average)); + painter.drawPoint(i,0); + } + pixmap = pix; + } else { + QPixmap pix = QPixmap(nb_pieces, 1); + pix.fill(); + QPainter painter(&pix); + for(int i=0; i < nb_pieces; ++i) { + painter.setPen(getPieceColor(avail[i], average)); + painter.drawPoint(i,0); + } + pixmap = pix; } } update(); Index: src/downloadedpiecesbar.h =================================================================== --- src/downloadedpiecesbar.h (revision 3245) +++ src/downloadedpiecesbar.h (revision 3248) @@ -36,6 +36,7 @@ #include <QList> #include <QPixmap> #include <libtorrent/bitfield.hpp> +#include <math.h> using namespace libtorrent; #define BAR_HEIGHT 18 @@ -55,19 +56,46 @@ void setProgress(bitfield pieces) { if(pieces.empty()) { // Empty bar - pixmap = QPixmap(1, 1); - QPainter painter(&pixmap); - painter.setPen(Qt::white); - painter.drawPoint(0,0); + QPixmap pix = QPixmap(1, 1); + pix.fill(); + pixmap = pix; } else { - pixmap = QPixmap(pieces.size(), 1); - QPainter painter(&pixmap); - for(uint i=0; i<pieces.size(); ++i) { - if(pieces[i]) - painter.setPen(Qt::blue); - else - painter.setPen(Qt::white); - painter.drawPoint(i,0); + int nb_pieces = pieces.size(); + // Reduce the number of pieces before creating the pixmap + // otherwise it can crash when there are too many pieces + if(nb_pieces > width()) { + int ratio = floor(nb_pieces/(double)width()); + QVector<bool> scaled_pieces; + for(int i=0; i<nb_pieces; i+= ratio) { + bool have = true; + for(int j=i; j<qMin(i+ratio, nb_pieces); ++j) { + if(!pieces[i]) { have = false; break; } + } + scaled_pieces << have; + } + QPixmap pix = QPixmap(scaled_pieces.size(), 1); + pix.fill(); + QPainter painter(&pix); + for(int i=0; i<scaled_pieces.size(); ++i) { + if(scaled_pieces[i]) + painter.setPen(Qt::blue); + else + painter.setPen(Qt::white); + painter.drawPoint(i,0); + } + pixmap = pix; + } else { + QPixmap pix = QPixmap(pieces.size(), 1); + pix.fill(); + QPainter painter(&pix); + for(uint i=0; i<pieces.size(); ++i) { + if(pieces[i]) + painter.setPen(Qt::blue); + else + painter.setPen(Qt::white); + painter.drawPoint(i,0); + } + pixmap = pix; } } update();