|
Hi!
We are using Erlang and specifically the erl_interface for C (Visual Studio C++ 2008, Windows 7) to connect to our Erlang servers. We have noticed weird errors when creating (and freeing) terms in different threads. It seems to me that the memory allocation module is not thread-aware. I have managed to isolate the problem and written an exemplary program (see end of mail) where several threads create and free erlang terms (tuples "{hello,world}"). The terms are continously checked for correctness by assertions (assert(type != ERL_UNDEF)). Note, that the terms are local in regard to the thread. When running a single thread, everything is just fine. No memory leaks, no exceptions, no assertions. However, when I use multiple threads something goes wrong (usually just several milliseconds after starting) and I get completely unpredictable results: - sometimes an atom that I have just created in the preceding line is suddenly a tuple (assertion fails) - sometimes a tuple references itself as a child, thus creating a recursion and a stack overflow when checking its children - sometimes the type of a term becomes ERL_UNDEF - etc. I have tried this with the precompiled binaries for version R12B05 and with the most recent version R14B02. (In the latter case I had to link with "ei_md.lib" and "erl_interface_md.lib", since I don't have the corresponding VS2005-Debug-Runtime-DLLs) Am I missing something obvious? Is this problem known or worked upon or is there any fix? I have searched the documentation and the web but I only found vague references to a compiler flag _REENTRANT, which would fix some pthreads concurrency issues. But judging from the Makefile I am using Win32-Threads (also I would like to get around having to build erl_interface with cygwin). Any help would be greatly appreciated, since this is a real show-stopper. Thanks in advance, Benni Here is the source code: #include <erl_interface.h> #include <boost/thread/thread.hpp> #include <boost/shared_ptr.hpp> #include <iostream> #include <vector> #include <time.h> // // select the number of threads that simultaneously allocate and // deallocate erlang terms: // const int numberOfThreads = 3; volatile bool abortThread = false; // // check whether the term is valid; recurse if we have a tuple // void checkTerm(const ETERM* p) { if (p) { int type = ERL_TYPE(p); assert( (type != ERL_UNDEF) && "invalid erlang term!" ); if (ERL_IS_TUPLE(p)) { for (int i = 0; i < ERL_TUPLE_SIZE(p); ++i) checkTerm( ERL_TUPLE_ELEMENT(p, i) ); } } } // // free the term; recurse if we have a tuple // (I could have used erl_free_compound() instead) // void deleteTerm(ETERM* p) { if (p) { if (ERL_IS_TUPLE(p)) { for (int i = 0; i < ERL_TUPLE_SIZE(p); ++i) deleteTerm( ERL_TUPLE_ELEMENT(p, i) ); } erl_free_term(p); } } // // the thread routine: // // holds 64 erlang terms (locally!), which are initially NULL. // in every iteration: // - one of the terms is replaced by a tuple {hello, world} // - every created tuple is checked for validity // - all 64 tuples are checked for validity as well // void threadRoutine() { // hold 64 erlang elements std::vector<ETERM*> terms(64, (ETERM*)0); while (!abortThread) { // check all terms for (std::size_t i = 0; i < terms.size(); ++i) checkTerm( terms[i] ); // pick random term int idx = rand() % (int)(terms.size()); // create atom ETERM* a = erl_mk_atom("hello"); checkTerm( a ); // create atom ETERM* b = erl_mk_atom("world"); checkTerm( b ); // create tuple {hello, world} ETERM* hw[2]; hw[0] = a; hw[1] = b; ETERM* tuple = erl_mk_tuple(hw, 2); checkTerm( tuple ); // replace current term with this tuple deleteTerm( terms[idx] ); terms[idx] = tuple; } // release all terms for (std::size_t i = 0; i < terms.size(); ++i) deleteTerm( terms[i] ); } typedef boost::shared_ptr< boost::thread > thread_ptr; // // main routine: // start the threads, wait for <Return>, stop the threads // int main(int argc, char* argv[]) { // init erl_init(NULL, 0); srand( (unsigned)time(NULL) ); // start threads std::vector< thread_ptr > threads; for (int i = 0; i < numberOfThreads; ++i) threads.push_back( thread_ptr( new boost::thread(&threadRoutine) ) ); // wait std::cout << "Press Return to stop" << std::endl; std::string str; std::getline(std::cin, str); // wait for threads abortThread = true; for (std::size_t i = 0; i < threads.size(); ++i) threads[i]->join(); } -- Benjamin Winkler Software Engineer SPECS Surface Nano Analysis GmbH Voltastrasse 5 13355 Berlin Germany Tel.: +49 30 46 78 24-92 47 Fax: +49 30 46 42 083 Email: [hidden email] Web: www.specs.com SPECS Surface Nano Analysis GmbH Innovation in Surface Spectroscopy and Microscopy Systems CEO: Reinhard Lembke Registered Office: Berlin Companies Commercial Register No.: 93 HRB 21390 Register Court: Charlottenburg This e-mail contains confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and delete this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden. _______________________________________________ erlang-bugs mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-bugs |
|
On Thu, Apr 07, 2011 at 09:53:05AM +0200, Benjamin Winkler wrote:
> Hi! > > We are using Erlang and specifically the erl_interface for C (Visual > Studio C++ 2008, Windows 7) to connect to our Erlang servers. We have > noticed weird errors when creating (and freeing) terms in different > threads. It seems to me that the memory allocation module is not > thread-aware. This isn't helpful with solving your problem with erl_interface but have you looked at the newer ei interface? It lets you manage the memory yourself (or allocates memory for you if you use the ei_x_* functions). The documentation is here: http://www.erlang.org/doc/man/ei.html _______________________________________________ erlang-bugs mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-bugs |
|
On Thu, Apr 07, 2011 at 01:08:37PM -0400, Michael Santos wrote:
> On Thu, Apr 07, 2011 at 09:53:05AM +0200, Benjamin Winkler wrote: > > Hi! > > > > We are using Erlang and specifically the erl_interface for C (Visual > > Studio C++ 2008, Windows 7) to connect to our Erlang servers. We have > > noticed weird errors when creating (and freeing) terms in different > > threads. It seems to me that the memory allocation module is not > > thread-aware. > > This isn't helpful with solving your problem with erl_interface but > have you looked at the newer ei interface? It lets you manage the memory > yourself (or allocates memory for you if you use the ei_x_* functions). > I'm pretty sure that the whole point of ei is to be a thread-safe replacement for erl_interface. Andrew _______________________________________________ erlang-bugs mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-bugs |
|
Am 07.04.2011 20:15, schrieb Andrew Thompson:
> On Thu, Apr 07, 2011 at 01:08:37PM -0400, Michael Santos wrote: >> On Thu, Apr 07, 2011 at 09:53:05AM +0200, Benjamin Winkler wrote: >>> Hi! >>> >>> We are using Erlang and specifically the erl_interface for C (Visual >>> Studio C++ 2008, Windows 7) to connect to our Erlang servers. We have >>> noticed weird errors when creating (and freeing) terms in different >>> threads. It seems to me that the memory allocation module is not >>> thread-aware. >> This isn't helpful with solving your problem with erl_interface but >> have you looked at the newer ei interface? It lets you manage the memory >> yourself (or allocates memory for you if you use the ei_x_* functions). > I'm pretty sure that the whole point of ei is to be a thread-safe > replacement for erl_interface. mutex to lock every single call to ETERM-allocation functions such as erl_mk_atom() and erl_free_term(). Tedious. However, I did not find any notice of that behaviour in the erl_interface documentation. Also, ei provides a function ei_decode_term() which references the erl_interface library, and I'm pretty sure that this is not thread-safe as well as the whole problem seems to be the memory allocation for erlang terms. So all in all the conclusion would be: stay away from ETERM? Benni _______________________________________________ erlang-bugs mailing list [hidden email] http://erlang.org/mailman/listinfo/erlang-bugs |
| Powered by Nabble | Edit this page |
