[tlbuild] dvisvgm-2.1 trial build

Richard M. Koch koch at uoregon.edu
Thu Feb 2 20:39:13 CET 2017


Karl and company,

I succeeded in building everything on Sierra. I got 406 executables and no test errors.

Looking more closely at my original log file, I discovered that all the errors came from
a single file,

	splinefont.h

which is in

	source/texk/dvisvgm/dvisvgm-src/libs/ff-wolf/fontforge

This file seems to have been written in 2000-2012 by George Williams. The errors come
from the last lines of this file, which deal with "threaded locals". Don't ask me what these
are. 

The interesting piece of code in splinefont.h starts with the following

	#ifdef _WIN32
	#define BAD_LOCALE_HACK
	typedef char* locale_t;
	#define LC_GLOBAL_LOCALE ((locale_t)-1)
	#define LC_ALL_MASK LC_ALL
	#define LC_COLLATE_MASK LC_COLLATE
	#define LC_CTYPE_MASK LC_CTYPE
	#define LC_MONETARY_MASK LC_MONETARY
	#define LC_NUMERIC_MASK LC_NUMERIC
	#define LC_TIME_MASK LC_TIME
	#endif

This is then followed by two fairly short code blocks, both of the form

	#ifndef BAD_LOCALE_HACK
	...
	#else
	...
	#endif

The file then has nine lines of code and that's that. 

The first #else above is followed by a comment:

	// Yes, it is dirty. But so is an operating system that doesn't support threaded locales

I think you can guess my fix. In the displayed code, I commented out "#ifdef _WIN32", so the block of
code applied to everyone, and of course commented out "#endif" at the end of the block.

--------------

Then I looked for "threaded locale" on the web and discovered that in Standard C, a locale is a global resource,
while in C++, it is a class and there can be several instances of the locale class. By itself, that is not a problem.
But can threads change locale?

Stackoverflow had more information:


3
down vote
 <>	
In the C++11 standard threads are now a supported part of the language. The standard explicitly calls out that setlocale() calls introduce data races with other calls to setlocale() or calls to functions that are affected by the current C locale including strtod(). The locale::global() function is considered to behave as-if it called setlocale(), so it also can introduce a data race (noted below).

On Linux with glibc it is MT-unsafe (const:locale env) <https://www.gnu.org/software/libc/manual/html_node/Setting-the-Locale.html#index-setlocale> to have threads call setlocale() concurrently with a non-NULL argument and call any other function which might use the global locale (data race and thus undefined behaviour in C11). It is suggested to use uselocale() <http://man7.org/linux/man-pages/man3/uselocale.3.html> instead which is MT-safe and changes only the calling thread's locale. On Linux with libstdc++ in C++ code you should avoid locale::global (process wide change) and create a locale for the thread's use (the locale::global is MT-unsafe for the same reasons as the C runtime). Given your goal to use strtod (a C API) you should use uselocale().

On Linux using glibc the setlocale() function itself is MT-unsafe unless you meet 2 strict criteria, and as required by POSIX changes the locale for the entire process. The new Linux man pages (part of the Red Hat and Fujitsu work to specify MT-safety notations for all APIs <http://man7.org/linux/man-pages/man7/attributes.7.html>) mark setlocale() <http://man7.org/linux/man-pages/man3/setlocale.3.html#ATTRIBUTES> as "MT-Unsafe const:locale env", which means that setlocale is MT-safe IFF you keep the locale constant (by not modifying it, just querying it by passing NULL), and if you keep the locale and environment constant (to avoid changes to the locale if the argument is ""). On Linux using glibc you should use uselocale() if you want to change just the locale of the calling thread, since this is MT-safe and does not rely on your environment in any way and strtod will use the thread's locale. Similarly all systems that implement POSIX should provide uselocale() for use in a thread context (MT-safe).

OS X implements uselocale() so you can use that.

On Windows use _configthreadlocale to change if setlocale() operates on the whole process or threads (turns it into uselocale which is what you need), but for C++ code you should again use an instance of the locale class and avoid locale::global <https://msdn.microsoft.com/en-us/library/ms235302.aspx>.



Maybe this information could be used to fix then TeXLive source so it will work on many more systems. Of course systems which do not support C++11 may have to avoid dvisvgm.

Dick Koch
koch at uoregon.edu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://tug.org/pipermail/tlbuild/attachments/20170202/63eccec7/attachment.html>


More information about the tlbuild mailing list