[fpc-pascal] Strings and Multithreading (case)

Jonas Maebe jonas.maebe at elis.ugent.be
Mon Sep 15 11:06:29 CEST 2008


On 14 Sep 2008, at 23:29, Nihilist wrote:

> Thread 1 checks for S=Nil an fpc_ansistr_decr_ref (svn version, 15.9.)
> Threadswitch to Thread 2
> Thread 2 checks runs the whole procedure, decrements reference count  
> to zero (only one reference (global)) and calls DisposeAnsiString
> * Evil case * Memory is reallocated by someone else in Thread2 and  
> filled with some nonsense
> Threadswitch to Thread 1
> Thread 1 runs the rest of fpc_ansistr_decr_ref, assume integer at S- 
> Firstoff is >0 we will suddenly decrement an integer inside a  
> foreign memory block
> * Very evil case* Integer was =1, we even free the memory again.  
> (with many following problems and exceptions)
>
> I really hope i am wrong. If i am not, my current solution is to put  
> a mutex around fpc_ansistr_decr_ref, but i know that this solution  
> is slow.

You have a race condition in your program anyway. Even if the incref/ 
decref stuff was completely atomic, depending on the scheduling order  
the final result would either be an empty string or the original  
string. It's debatable whether it's better for data races to cause  
crashes or not, since they can be extremely difficult to debug if they  
don't (not that it's easy if they do, but at least it's more apparent  
where there may be a problem).

I think it only makes sense to guarantee thread safety of ref-counted  
objects to the extent that you do not have any race conditions in your  
program (at the semantic level, i.e., which outcome a particular  
operation will have depending on the scheduling order even if all  
operations are atomic). Otherwise the results will be unpredictable  
anyway.

There are several more problems besides fpc_AnsiStr_Assign() if you  
have such race conditions (e.g. in one thread passing the global  
string by value, so fpc_ansistr_incr_ref gets() called, while calling  
finalize() on the string in another thread (so fpc_ansistr_decr_ref()  
gets called).


Jonas



More information about the fpc-pascal mailing list