| Ticket UUID: | 1967630 | ||
| Title: | tclLoadDl.c dlerror() is not thread safe | ||
| Type: | Bug | Created on: | 2008-05-20 04:15:19 |
| Submitter: | georgeps | Assigned to: | jan.nijtmans |
| Subsystem: | 40. Dynamic Loading | Severity: | Minor |
| Priority: | 5 Medium | Last modified: | 2026-10-28 21:07:40 |
| Status: | Closed | Closed by: | jan.nijtmans |
| Resolution: | Fixed | Closed on: | 2026-10-28 21:07:40 |
| Version: | 9.1.0 | ||
| Description: | ||||
According to the standard for dlerror(), it's not required to be thread-safe. http://www.opengroup.org/onlinepubs/009695399/functions/dlerror.html I also checked several open source libc. NetBSD and OpenBSD don't use thread-specific storage for dlerror messages, but the GNU/Linux glibc does. Attached is a patch to fix the problem. It drains the dlerror() first after entering the critical region. The Linux usage suggested is slightly different than what BSD seems to suggest. The glibc dlsym manual suggests using dlerror to indicate the success or failure of a dlsym(), rather than NULL from the return of dlsym(), because apparently dlsym() can return 0/NULL and still have succeeded (with some symbols). So the logic should probably be changed further based on what the glibc docs say. This is the example taken from the manual for dlsym: dlerror(); /* Clear any existing error */ cosine = dlsym(handle, "cos"); if ((error = dlerror()) != NULL) ... I also added error handling to TclpFindSymbol(). It appears to be unfinished prior to this, or the usage expectations of it have changed, because in the HEAD it doesn't use the interp argument to report an error like the (outdated?) comments state. | ||||
| User Comments: | ||||
georgeps added on 2008-05-20 11:15:19:
File Added - 278384: tclLoadDl-2.patch nijtmans added on 2008-05-20 14:59:00:
Logged In: YES
user_id=61031
Originator: NO
In functions like TclLoadFile and TclpLoadFile, TclpFindSymbol()
is used multiple times and is not expected to modify the interp
result. At least those functions need to be modified to reset
the interp result after the last TclpFindSymbol() call.
Further on, the same modification will be needed in tclLoadDyld.c
as well (if the Mac-implementation is not thread-safe), and the
TclpFindSymbol change is needed in tclLoadNext.c, tclLoadOSF.c,
tclLoadShl.c and tclWinLoad.c as well.
In practice, I doubt that this ever will be a practical
problem, because normally all libraries are loaded in a
single thread at start-up. But - strictly speaking - yes,
I agree that the mutex should be there and TclpFindSymbol
should leave an error-message in interp result as documented.
Regards,
Jan Nijtmans
serhiy.storchaka added on 2026-10-25 11:49:46:
Reproduced on NetBSD 10.1 and OpenBSD 7.9, where the dlerror() state is process-wide: a failing [load] concurrent with a successful [load] in another thread gets the other thread's message or NULL, and NULL crashes in Tcl_ObjPrintf(). Linux, FreeBSD and macOS keep it per thread. Proposed fix in branch unix-dlerror-mutex, based on the attached patch: a mutex from dlopen()/dlsym() until dlerror() has been read, and "unknown" for a NULL message. It only covers Tcl's own calls, not dlopen() by other code in the process. jan.nijtmans added on 2026-10-28 21:07:40:
Fixed in [e0e0341124|trunk], core-9-0-branch and core-8-6-branch Many thanks! | ||||
Attachments:
- tclLoadDl-2.patch [download] added by georgeps on 2008-05-20 11:15:19. [details]
