Bug 139197

Summary: crash during import of raw imagefiles (dng)
Product: [Applications] digikam Reporter: Juergen Helmers <juergen.helmers>
Component: Plugin-DImg-JPEGAssignee: Digikam Developers <digikam-bugs-null>
Status: RESOLVED FIXED    
Severity: crash CC: caulier.gilles
Priority: NOR    
Version: 0.9.0   
Target Milestone: ---   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed In: 0.9.1
Sentry Crash Report:
Attachments: backtrace for digikam crash during raw dng-file import

Description Juergen Helmers 2006-12-24 22:13:16 UTC
Version:           0.9.0 (using KDE 3.5.5 "release 45" , openSUSE 10.2)
Compiler:          Target: i586-suse-linux
OS:                Linux (i686) release 2.6.18.2-34-default

When trying to import a bunch of raw image files from a pentax k10d (all files in dng raw format) digikam crashes on the first file it has to rotate according to exif data. (the option is set in the import dialog). Images in landscape format are imported fine up to the first portrait file, when the app crashes completly. Dcraw version installed is stocl suse 10.2 which is:

v8.40

Cheers Juergen
Comment 1 Bram Schoenmakers 2006-12-24 23:01:59 UTC
Please provide a backtrace.
Comment 2 Juergen Helmers 2006-12-25 09:56:58 UTC
Created attachment 19028 [details]
backtrace for digikam crash during raw dng-file import

Hi!
I have recompiled digikam from source enabling full debug support. The
attachment is the backtrace I have created using gdb.

Cheers Juergen
Comment 3 Marcel Wiesweg 2006-12-25 13:58:04 UTC
Exif autorotation is only available for JPEG files.

Nevertheless, the program must not crash.
To get the backtrace out of gdb, you have to type "bt" or, for all threads, "thr appl all bt" at the prompt. But this does not look like a crash, in this case, gdb would stop at the line number that causes the crash. In your log, the program has exited.
If you run it outside gdb, does the KDE crash handler (Dr.Konqui) appear? Or what happens?
Comment 4 Juergen Helmers 2006-12-26 11:13:24 UTC
I will repeat the backtrace as soon as possible. The app crashes silently, meaning, disappears into oblivion. The KDE crash handler does not appear. I didn't know that the auto rotation only applies to jpeg. I have turned it off which solves the problem for me as autorotation for my point and shoot camera doesn't work anyway. 
Anything else I could do beside the repetition of the backtrace?
Cheers Juergen
Comment 5 Marcel Wiesweg 2006-12-26 16:43:12 UTC
If it does not crash you dont need to repeat the backtrace, there will be none.
Perhaps you can add a breakpoint for the exit function?
Before the "run" command in gdb, type "br exit" and answer the question with yes. Perhaps the same with "br abort".
When the program has crashed, check if the "bt" command produces something useful, other than 
#0  0xb5d56246 in exit () from /lib/libc.so.6
#1  0xb5d40880 in __libc_start_main () from /lib/libc.so.6
#2  0x08049a71 in _start ()
Comment 6 Juergen Helmers 2006-12-27 16:38:49 UTC
Hi!

I have done as instructed, doing the folowing:

#gdb /opt/kde/bin/digikam
(gdb)br exit 
(y)
(gdb)br abort 
(y)
(gdb)run

...

[Thread -1316242544 (LWP 4357) exited]
[New Thread -1316242544 (LWP 4364)]
digikam: Dirty: /2006-12-24
digikam: Dirty: /
QDate::fromString: Parameter out of range
QDate::fromString: Parameter out of range
QDate::fromString: Parameter out of range
QDate::fromString: Parameter out of range
digikam: Dirty: /
QDate::fromString: Parameter out of range
QDate::fromString: Parameter out of range
digikam: Exif autorotate: imgp0236.dng using (/home/anja/Documents/Pictures/2006-12-24/.digikam-camera-tmp1-4100)
Warning: Size 77824 of Exif.Image.0xc634 exceeds 4096 bytes limit. Not decoded.
digikam: Exif Orientation: 6
Not a JPEG file: starts with 0x4d 0x4d
[Switching to Thread -1316242544 (LWP 4364)]

Breakpoint 3, 0xb6162af6 in exit () from /lib/libc.so.6
(gdb) bt

#0  0xb6162af6 in exit () from /lib/libc.so.6
#1  0xb785db36 in jpeg_std_error () from /usr//lib/libjpeg.so.62
#2  0x00000001 in ?? ()
#3  0x086d2df8 in ?? ()
#4  0x00000188 in ?? ()
#5  0xb7861ff4 in ?? () from /usr//lib/libjpeg.so.62
#6  0xb7861ff4 in ?? () from /usr//lib/libjpeg.so.62
#7  0x086ee96c in ?? ()
#8  0xb18ba728 in ?? ()
#9  0xb7852236 in jpeg_set_marker_processor () from /usr//lib/libjpeg.so.62
#10 0xb7852236 in jpeg_set_marker_processor () from /usr//lib/libjpeg.so.62
#11 0xb7850bec in jinit_input_controller () from /usr//lib/libjpeg.so.62
#12 0xb784f073 in jpeg_consume_input () from /usr//lib/libjpeg.so.62
#13 0xb784f438 in jpeg_read_header () from /usr//lib/libjpeg.so.62
#14 0xb7e347c8 in Digikam::exifRotate (file=@0xb18bb0d4,
    documentName=@0xb18bae7c) at jpegutils.cpp:178
#15 0xb7e7446b in Digikam::CameraThread::run (this=0x869f3c0)
    at cameracontroller.cpp:385
#16 0xb68e1435 in QThreadInstance::start () from /usr//lib/libqt-mt.so.3
#17 0xb657c112 in start_thread () from /lib/libpthread.so.0
#18 0xb61f62ee in clone () from /lib/libc.so.6
(gdb)

Hope this helps!

Cheers Juergen
Comment 7 Marcel Wiesweg 2006-12-27 22:31:06 UTC
SVN commit 617056 by mwiesweg:

In jpegutils, use proper libjpeg error handling, as it is done in the jpegloader.
Sometimes the mimetype detection may fail, and libjpeg would call exit()
from the default error handler.

BUG: 139197


 M  +70 -5     jpegutils.cpp  


--- trunk/extragear/graphics/digikam/libs/jpegutils/jpegutils.cpp #617055:617056
@@ -35,6 +35,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <utime.h>
+#include <setjmp.h>
 #include <jpeglib.h>
 }
 
@@ -59,6 +60,54 @@
 namespace Digikam
 {
 
+// To manage Errors/Warnings handling provide by libjpeg
+
+//#define ENABLE_DEBUG_MESSAGES
+
+struct jpegutils_jpeg_error_mgr : public jpeg_error_mgr
+{
+    jmp_buf setjmp_buffer;
+};
+
+static void jpegutils_jpeg_error_exit(j_common_ptr cinfo);
+static void jpegutils_jpeg_emit_message(j_common_ptr cinfo, int msg_level);
+static void jpegutils_jpeg_output_message(j_common_ptr cinfo);
+
+static void jpegutils_jpeg_error_exit(j_common_ptr cinfo)
+{
+    jpegutils_jpeg_error_mgr* myerr = (jpegutils_jpeg_error_mgr*) cinfo->err;
+
+    char buffer[JMSG_LENGTH_MAX];
+    (*cinfo->err->format_message)(cinfo, buffer);
+
+#ifdef ENABLE_DEBUG_MESSAGES
+    DDebug() << k_funcinfo << buffer << endl;
+#endif
+
+    longjmp(myerr->setjmp_buffer, 1);
+}
+
+static void jpegutils_jpeg_emit_message(j_common_ptr cinfo, int msg_level)
+{
+    Q_UNUSED(msg_level)
+    char buffer[JMSG_LENGTH_MAX];
+    (*cinfo->err->format_message)(cinfo, buffer);
+
+#ifdef ENABLE_DEBUG_MESSAGES
+    DDebug() << k_funcinfo << buffer << " (" << msg_level << ")" << endl;
+#endif
+}
+
+static void jpegutils_jpeg_output_message(j_common_ptr cinfo)
+{
+    char buffer[JMSG_LENGTH_MAX];
+    (*cinfo->err->format_message)(cinfo, buffer);
+
+#ifdef ENABLE_DEBUG_MESSAGES
+    DDebug() << k_funcinfo << buffer << endl;
+#endif
+}
+
 bool exifRotate(const QString& file, const QString& documentName)
 {
     QFileInfo fi(file);
@@ -142,17 +191,21 @@
     
         struct jpeg_decompress_struct srcinfo;
         struct jpeg_compress_struct   dstinfo;
-        struct jpeg_error_mgr jsrcerr, jdsterr;
+        struct jpegutils_jpeg_error_mgr jsrcerr, jdsterr;
         jvirt_barray_ptr* src_coef_arrays;
         jvirt_barray_ptr* dst_coef_arrays;
     
         // Initialize the JPEG decompression object with default error handling
-        srcinfo.err = jpeg_std_error(&jsrcerr);
-        jpeg_create_decompress(&srcinfo);
+        srcinfo.err                 = jpeg_std_error(&jsrcerr);
+        srcinfo.err->error_exit     = jpegutils_jpeg_error_exit;
+        srcinfo.err->emit_message   = jpegutils_jpeg_emit_message;
+        srcinfo.err->output_message = jpegutils_jpeg_output_message;
     
         // Initialize the JPEG compression object with default error handling
-        dstinfo.err = jpeg_std_error(&jdsterr);
-        jpeg_create_compress(&dstinfo);
+        dstinfo.err                 = jpeg_std_error(&jdsterr);
+        dstinfo.err->error_exit     = jpegutils_jpeg_error_exit;
+        dstinfo.err->emit_message   = jpegutils_jpeg_emit_message;
+        dstinfo.err->output_message = jpegutils_jpeg_output_message;
     
         FILE *input_file;
         FILE *output_file;
@@ -172,6 +225,18 @@
             return false;
         }
     
+        if (setjmp(jsrcerr.setjmp_buffer) || setjmp(jdsterr.setjmp_buffer))
+        {
+            jpeg_destroy_decompress(&srcinfo);
+            jpeg_destroy_compress(&dstinfo);
+            fclose(input_file);
+            fclose(output_file);
+            return false;
+        }
+
+        jpeg_create_decompress(&srcinfo);
+        jpeg_create_compress(&dstinfo);
+        
         jpeg_stdio_src(&srcinfo, input_file);
         jcopy_markers_setup(&srcinfo, copyoption);
         
Comment 8 caulier.gilles 2007-01-03 09:29:02 UTC
*** Bug 139273 has been marked as a duplicate of this bug. ***
Comment 9 caulier.gilles 2007-01-03 09:36:38 UTC
Marcel,

I suspect than we can have the same problem into JPEGLossLess kipi-plugin into jpegtranform.cpp implementation witch use libjpeg.

http://websvn.kde.org/trunk/extragear/libs/kipi-plugins/jpeglossless/jpegtransform.cpp?rev=592621&view=auto

I recommend you to backport your patch into this implementation too...

Gilles

note : ooooh, i have forget to fix the kddebug() to qdebug() statements in this multithreaded plugin (:=)))... I will do it.
Comment 10 Marcel Wiesweg 2007-01-03 17:27:20 UTC
SVN commit 619526 by mwiesweg:

Port back fix for digikam bug 139197 to JPEGLossLess:
Use proper libjpeg error handling.
In case of an error, libjpeg would call exit() from the default error handler.

CCBUG: 139197


 M  +70 -5     jpegtransform.cpp  


--- trunk/extragear/libs/kipi-plugins/jpeglossless/jpegtransform.cpp #619525:619526
@@ -32,6 +32,7 @@
 {
 #include <sys/types.h>
 #include <unistd.h>
+#include <setjmp.h>
 #include <jpeglib.h>
 }
 
@@ -66,6 +67,54 @@
 Matrix Matrix::rotate90flipVertical   ( 0, -1, -1,  0);
 
 
+// To manage Errors/Warnings handling provide by libjpeg
+
+//#define ENABLE_DEBUG_MESSAGES
+
+struct jpegtransform_jpeg_error_mgr : public jpeg_error_mgr
+{
+    jmp_buf setjmp_buffer;
+};
+
+static void jpegtransform_jpeg_error_exit(j_common_ptr cinfo);
+static void jpegtransform_jpeg_emit_message(j_common_ptr cinfo, int msg_level);
+static void jpegtransform_jpeg_output_message(j_common_ptr cinfo);
+
+static void jpegtransform_jpeg_error_exit(j_common_ptr cinfo)
+{
+    jpegtransform_jpeg_error_mgr* myerr = (jpegtransform_jpeg_error_mgr*) cinfo->err;
+
+    char buffer[JMSG_LENGTH_MAX];
+    (*cinfo->err->format_message)(cinfo, buffer);
+
+#ifdef ENABLE_DEBUG_MESSAGES
+    kdDebug() << k_funcinfo << buffer << endl;
+#endif
+
+    longjmp(myerr->setjmp_buffer, 1);
+}
+
+static void jpegtransform_jpeg_emit_message(j_common_ptr cinfo, int msg_level)
+{
+    Q_UNUSED(msg_level)
+    char buffer[JMSG_LENGTH_MAX];
+    (*cinfo->err->format_message)(cinfo, buffer);
+
+#ifdef ENABLE_DEBUG_MESSAGES
+    kdDebug() << k_funcinfo << buffer << " (" << msg_level << ")" << endl;
+#endif
+}
+
+static void jpegtransform_jpeg_output_message(j_common_ptr cinfo)
+{
+    char buffer[JMSG_LENGTH_MAX];
+    (*cinfo->err->format_message)(cinfo, buffer);
+
+#ifdef ENABLE_DEBUG_MESSAGES
+    kdDebug() << k_funcinfo << buffer << endl;
+#endif
+}
+
 bool transformJPEG(const QString& src, const QString& destGiven,
                    Matrix &userAction, QString& err)
 {
@@ -80,7 +129,7 @@
 
     struct jpeg_decompress_struct srcinfo;
     struct jpeg_compress_struct dstinfo;
-    struct jpeg_error_mgr jsrcerr, jdsterr;
+    struct jpegtransform_jpeg_error_mgr jsrcerr, jdsterr;
     jvirt_barray_ptr * src_coef_arrays;
     jvirt_barray_ptr * dst_coef_arrays;
 
@@ -88,12 +137,16 @@
     JXFORM_CODE flip,rotate;
 
     // Initialize the JPEG decompression object with default error handling
-    srcinfo.err = jpeg_std_error(&jsrcerr);
-    jpeg_create_decompress(&srcinfo);
+    srcinfo.err                 = jpeg_std_error(&jsrcerr);
+    srcinfo.err->error_exit     = jpegtransform_jpeg_error_exit;
+    srcinfo.err->emit_message   = jpegtransform_jpeg_emit_message;
+    srcinfo.err->output_message = jpegtransform_jpeg_output_message;
 
     // Initialize the JPEG compression object with default error handling
-    dstinfo.err = jpeg_std_error(&jdsterr);
-    jpeg_create_compress(&dstinfo);
+    dstinfo.err                 = jpeg_std_error(&jdsterr);
+    dstinfo.err->error_exit     = jpegtransform_jpeg_error_exit;
+    dstinfo.err->emit_message   = jpegtransform_jpeg_emit_message;
+    dstinfo.err->output_message = jpegtransform_jpeg_output_message;
 
     FILE *input_file;
     FILE *output_file;
@@ -115,6 +168,18 @@
         return false;
     }
 
+    if (setjmp(jsrcerr.setjmp_buffer) || setjmp(jdsterr.setjmp_buffer))
+    {
+        jpeg_destroy_decompress(&srcinfo);
+        jpeg_destroy_compress(&dstinfo);
+        fclose(input_file);
+        fclose(output_file);
+        return false;
+    }
+
+    jpeg_create_decompress(&srcinfo);
+    jpeg_create_compress(&dstinfo);
+
     jpeg_stdio_src(&srcinfo, input_file);
     jcopy_markers_setup(&srcinfo, copyoption);