Can DCMTK be used in multithreaded application in some limited way?

All other questions regarding DCMTK

Moderator: Moderator Team

Post Reply
Message
Author
akaraivanov
Posts: 6
Joined: Fri, 2004-12-03, 11:34
Location: Denmark

Can DCMTK be used in multithreaded application in some limited way?

#1 Post by akaraivanov »

I saw in the FAQ (Q #18 ) that DCMTK is generally not thread safe.

My question is if it is possible to use dcmnet in a multithreaded application in some restricted way that would be safe?
For example, let's say we have an application with two threads.
The first is doing c-find while the second move-scu/storescp. If the threads use their own (private) association and network objects will that be safe or there are some other global objects in DCMTK that should be protected and at present they are not?

Marco Eichelberg
OFFIS DICOM Team
OFFIS DICOM Team
Posts: 1437
Joined: Tue, 2004-11-02, 17:22
Location: Oldenburg, Germany
Contact:

#2 Post by Marco Eichelberg »

First of all, we have never really tried this, so all comments below should be taken with care. The answer to your question depends on the platform. On Windows, all winsock functions are thread safe, so the only thing that would need to be protected are global and static objects, including a static buffer in which error messages are formatted and the table that implements the finite automaton for the DUL protocol. This table should be initialized once and will be re-used for multiple associations. On Posix platforms, you will additionally need to exchange all functions that are not thread safe by thread safe variants. This includes (but is not limited to) strerror_r, localtime_r, gethostbyname_r. Configure tests will be needed for most of the _r functions because there are not available with every Unix dialect supported by DCMTK.

akaraivanov
Posts: 6
Joined: Fri, 2004-12-03, 11:34
Location: Denmark

#3 Post by akaraivanov »

Thank you very much for the prompt reply!

I am interested in making this to work on UNIX. I wanted to check if this can be done and to have an idea how big effort that is.

I made a very quick check (just grepping in the source) for _r functions if they are used in DCMTK. The result is:

ctime and rand should be replaced with their _r versions - these are used in very few places.
strerror - there is a check for strerror_r in configure and that is used in only one place. The rest of the places use just strerror and they do not check for the macro (HAVE_STRERROR_R).
tmpnam is used in a safe way but may be it better be replaced by mkstemp.

I have not looked into the DUL table issue but sounds as an easy one. Once initialized is this table read-only ?

Can you think of anything else that should be protected?

Marco Eichelberg
OFFIS DICOM Team
OFFIS DICOM Team
Posts: 1437
Joined: Tue, 2004-11-02, 17:22
Location: Oldenburg, Germany
Contact:

#4 Post by Marco Eichelberg »

There are probably a few more functions that need to be replaced by thread-safe counterparts. This is an article I looked up some time ago when I created an entry for this topic in our internal to-do list:
Page 32 of the 1996 Posix.1 standard says "All functions defined by Posix.1 and the C standard shall be thread-safe, except that the following functions need not be thread-safe:
asctime()
ctime()
getc_unlocked()*
getchar_unlocked()*
getgrid()
getgrnam()
getlogin()
getpwnam()
getpwuid()
gmtime()
localtime()
putc_unlocked()*
putchar_unlocked()*
rand()
readdir()
strtok()
ttyname()"

Note that a thread-safe XXX_r() version of the above are available, other than those with an asterisk. Also note that ctermid() and tmpnam() are only thread-safe if a nonnull pointer is used as an argument.

However, POSIX and ANSI C specify only a small part of the "traditional UNIX programming environment", though it's a start. The real danger in reading the POSIX list is that most people don't really know what's included. While an inclusive list would be better than an exclusive list, that'd be awfully long and awkward.

The Open Group (OSF and X/Open) has extended the Single UNIX specification
(also known as "SPEC1170" for it's 1,170 UNIX interfaces, or UNIX95) to include POSIX.1b-1993 realtime, POSIX.1c-1995 threads, and various extensions. It's called the Single UNIX Specification, Version 2; or UNIX98. Within this calendar year, it's safe to assume that most UNIX versions currently branded by The Open Group (as XPG3, UNIX93, UNIX95) will extend their brand validation to UNIX98.

The interfaces specification part of the Single UNIX Specification, Version 2 (known as XSH5), in section 2.8.2, "Thread-safety", specifies that all interfaces defined by THIS specification will be thread-safe, except for "the following". There are two explicit lists, and one implicit. One is the POSIX list already quoted by Rich Stevens. The second is an additional list of X/Open interfaces:

basename dbm_open fcvt getutxline pututxline
catgets dbm_store gamma getw setgrent
dbm_clearerr dirname gcvt l64a setkey
dbm_close drand48 getdate lgamma setpwent
dbm_delete ecvt getenv lrand48 setutxent
dbm_error encrypt getgrent mrand48 strerror
dbm_fetch endgrent getpwent nl_langinfo
dbm_firstkey endpwent getutxent ptsname
dbm_nextkey endutxent getutxid putenv

The implicit list is a statement that all interfaces in the "Legacy" feature group need not be thread-safe. From another section, that list is:

advance gamma putw sbrk wait3
brk getdtablesize re_comp sigstack
chroot getpagesize re_exec step
compile getpass regcmp ttyslot
cuserid getw regex valloc
<regexp.h> <varargs.h> <re_comp.h>
loc1 __loc1 loc2 locs

Obviously, this is still an exclusive list rather than inclusive. But then, if UNIX95 had 1,170 interfaces, and UNIX98 is bigger, an inclusive list would be rather awkward. (And don't expect ME to type it into the newsgroup!)

On the other hand... beware that if you've got a system that doesn't claim conformance to POSIX 1003.1c-1995 (or POSIX 1003.1-1996, which includes it), then you're not guaranteed to be able to rely even on the POSIX list, much less the X/Open list. It's reasonable to assume that any
implementation's libpthread (or equivalent, though that name has become pretty much defacto standard) is thread-safe. And it's probably reasonable to assume, unless specified otherwise, that "the most common" bits of libc are thread-safe. But without a formal statement of POSIX conformance, you're just dealing with "good will". And, even at that, POSIX conformance isn't validated -- so without validation by the UNIX98 branding test suite, you've got no real guarantee of anything.
At least getenv, readdir, rand and wait3 are used in some places in the toolkit. The rest should be fairly simple, however, a careful walk-through of all source code in module dcmnet is certainly a good idea, there might be an odd static variable here or there since the code is pretty old (1993).

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest