Skip to content

Commit ae87a95

Browse files
committed
TurboJPEG: Make global error handling thread-safe
... on platforms that support thread-local storage. This currently includes all supported platforms except 32-bit macOS. Fixes #396
1 parent b443c54 commit ae87a95

6 files changed

Lines changed: 28 additions & 4 deletions

File tree

CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,21 @@ if(NOT INLINE_WORKS)
451451
endif()
452452
message(STATUS "INLINE = ${INLINE} (FORCE_INLINE = ${FORCE_INLINE})")
453453

454+
if(WITH_TURBOJPEG)
455+
if(MSVC)
456+
set(THREAD_LOCAL "__declspec(thread)")
457+
else()
458+
set(THREAD_LOCAL "__thread")
459+
endif()
460+
check_c_source_compiles("${THREAD_LOCAL} int i; int main(void) { i = 0; return i; }" HAVE_THREAD_LOCAL)
461+
if(HAVE_THREAD_LOCAL)
462+
message(STATUS "THREAD_LOCAL = ${THREAD_LOCAL}")
463+
else()
464+
message(WARNING "Thread-local storage is not available. The TurboJPEG API library's global error handler will not be thread-safe.")
465+
unset(THREAD_LOCAL)
466+
endif()
467+
endif()
468+
454469
if(UNIX AND NOT APPLE)
455470
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/conftest.map "VERS_1 { global: *; };")
456471
set(CMAKE_REQUIRED_FLAGS

ChangeLog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ header and that maximum value was less than 255. libjpeg-turbo 1.5.0 already
2222
included a similar fix for binary PPM/PGM files with maximum values greater
2323
than 255.
2424

25+
4. The TurboJPEG API library's global error handler, which is used in functions
26+
such as `tjBufSize()` and `tjLoadImage()` that do not require a TurboJPEG
27+
instance handle, is now thread-safe on platforms that support thread-local
28+
storage.
29+
2530

2631
2.0.4
2732
=====

doc/html/group___turbo_j_p_e_g.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2129,7 +2129,7 @@ <h2 class="groupheader">Function Documentation</h2>
21292129
<p>Returns a descriptive error message explaining why the last command failed. </p>
21302130
<dl class="params"><dt>Parameters</dt><dd>
21312131
<table class="params">
2132-
<tr><td class="paramname">handle</td><td>a handle to a TurboJPEG compressor, decompressor, or transformer instance, or NULL if the error was generated by a global function (but note that retrieving the error message for a global function is not thread-safe.)</td></tr>
2132+
<tr><td class="paramname">handle</td><td>a handle to a TurboJPEG compressor, decompressor, or transformer instance, or NULL if the error was generated by a global function (but note that retrieving the error message for a global function is thread-safe only on platforms that support thread-local storage.)</td></tr>
21332133
</table>
21342134
</dd>
21352135
</dl>

jconfigint.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
/* How to obtain function inlining. */
88
#define INLINE @INLINE@
99

10+
/* How to obtain thread-local storage */
11+
#define THREAD_LOCAL @THREAD_LOCAL@
12+
1013
/* Define to the full name of this package. */
1114
#define PACKAGE_NAME "@CMAKE_PROJECT_NAME@"
1215

turbojpeg.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C)2009-2019 D. R. Commander. All Rights Reserved.
2+
* Copyright (C)2009-2020 D. R. Commander. All Rights Reserved.
33
*
44
* Redistribution and use in source and binary forms, with or without
55
* modification, are permitted provided that the following conditions are met:
@@ -43,6 +43,7 @@
4343
#include "transupp.h"
4444
#include "./jpegcomp.h"
4545
#include "./cdjpeg.h"
46+
#include "jconfigint.h"
4647

4748
extern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **, unsigned long *,
4849
boolean);
@@ -55,7 +56,7 @@ extern void jpeg_mem_src_tj(j_decompress_ptr, const unsigned char *,
5556

5657
/* Error handling (based on example in example.txt) */
5758

58-
static char errStr[JMSG_LENGTH_MAX] = "No error";
59+
static THREAD_LOCAL char errStr[JMSG_LENGTH_MAX] = "No error";
5960

6061
struct my_error_mgr {
6162
struct jpeg_error_mgr pub;

turbojpeg.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1650,7 +1650,7 @@ DLLEXPORT void tjFree(unsigned char *buffer);
16501650
* @param handle a handle to a TurboJPEG compressor, decompressor, or
16511651
* transformer instance, or NULL if the error was generated by a global
16521652
* function (but note that retrieving the error message for a global function
1653-
* is not thread-safe.)
1653+
* is thread-safe only on platforms that support thread-local storage.)
16541654
*
16551655
* @return a descriptive error message explaining why the last command failed.
16561656
*/

0 commit comments

Comments
 (0)