I have been writing a SOAP client application in C++ on Ubuntu using OpenSSL for my HTTPS transport and pthreads for threading. I have a number of threads – one central data acquisition thread which periodically gets worker threads to make SOAP requests via shared mutex protected queues.
Reading the documentation for OpenSSL I found Is OpenSSL thread-safe? in the OpenSSL FAQ which describes the mechanisms required to ensure thread safety when using OpenSSL. I implemented this and all works fine.
The reason for my question is a conceptual difficulty really. I was thinking about implementing the same functionality that my application has already, but instead of using threads, I would create 2 seperate applications : One for the worker thread (of which multiple copies would be running) and another for the main data acquisition thread. I would then use TCP sockets to communicate between the two rather than mutex protected queues. This may be a bad idea but that is not really important – what is confusing me is would I have to implement the same functions required to ensure OpenSSL thread safety in this second approach or not?
My guess is that I would not have to and they could be treated as independent (indeed surely it must be as so many applications use OpenSSL) but what is the reason for it?? What is different between multiple applications using shared library code and multiple threads sharing the same code?? I have been writing multithreaded applications successfully for a couple of years now and it concerns me that I cannot come up with an answer to this question.
The difference is that when multiple threads share the same library code, they also share the same global data structures; when multiple processes share that library code, they don’t.
For example, many of the cryptographic algorithms in OpenSSL are faster if they have a large precalculated table available. This table is shared between multiple threads calling the same OpenSSL functions, but locking must be used to ensure that only one thread attempts to initialise the table on first use.
As another example, many OpenSSL functions internally access the random number generator, but the state of this is a global data structure that must have its accessed synchronised across threads.