digitalmars.D - Are the _d_arrayappend functions, thread-safe?
- Jeff Davey (41/41) Jun 18 2007 I've recently been having problems with a small SMTP app when I have ser...
- Sean Kelly (3/3) Jun 18 2007 Looking at the code, it should be fine. I don't suppose you're trying
- Jeff Davey (5/7) Jun 18 2007 Nope.
- Jeff Davey (28/29) Jun 19 2007 Alright, I don't know if I can assume this anymore.
- Jeff Davey (24/24) Jun 19 2007 Ack, I pasted the wrong function (that one was a result of some debuggin...
- Sean Kelly (3/5) Jun 29 2007 Same here.
I've recently been having problems with a small SMTP app when I have serious multi-threaded load on linux (compiled with DMD 1.016). At first, it started with anything that uses std.string.format, and dies in _d_arrayappendcT.. so I removed all calls to anything that uses that module: (gdb) bt Die: DW_TAG_<unknown> (abbrev = 6, offset = 324) has children: FALSE attributes: DW_AT_byte_size (DW_FORM_data1) constant: 8 DW_AT_type (DW_FORM_ref4) constant ref: 307 (adjusted) Dwarf Error: Cannot find type of die [in module /root/smtp] The next place this problem occurred is std.string.split, with again, the _d_arrayappendcT function: (gdb) bt Die: DW_TAG_<unknown> (abbrev = 6, offset = 324) has children: FALSE attributes: DW_AT_byte_size (DW_FORM_data1) constant: 8 DW_AT_type (DW_FORM_ref4) constant ref: 307 (adjusted) Dwarf Error: Cannot find type of die [in module /root/smtp] So, I removed the std.string.split calls, and wrote my own that pre-allocated the array rather than appends to it, and that fixed that issue. And then, somewhere else (where I just have a regular array append): (gdb) bt Die: DW_TAG_<unknown> (abbrev = 6, offset = 324) has children: FALSE attributes: DW_AT_byte_size (DW_FORM_data1) constant: 8 DW_AT_type (DW_FORM_ref4) constant ref: 307 (adjusted) Dwarf Error: Cannot find type of die [in module /root/smtp] This time, it's in a slightly different function _d_arrayappendT. Basically the software has about 200 receiving threads, and is receiving around 60mbit/s of network traffic in a stress test. It's definitely thread related, as running it with only one thread it performs fine through 130,000 different emails. The threading model is fairly simple, accept a socket, pass that socket to a working thread, let the working thread clean up that socket. The only globals being used (other than anything in phobos) are contained to a wrapper "SocketStream" class, that has private variables, and one stream per class is created during the beginning of the work phase. I'm "pretty" certain it's not something on my side, but I would like to be mistaken.
Jun 18 2007
Looking at the code, it should be fine. I don't suppose you're trying to append to a single array from >1 thread simultaneously? Sean
Jun 18 2007
Sean Kelly Wrote:Looking at the code, it should be fine. I don't suppose you're trying to append to a single array from >1 thread simultaneously?Nope. I was trying to track down possible memory corruption with valgrind.. but apparently valgrind doesn't deal with pausing the threads for the gc to go off (Gives "Unrecognized instruction 0x66 0x60 0xB9 0x20"). I had a look at the array append stuff myself, it looks like things are getting locked up properly, but I don't have enough knowledge to track this down. I guess I'll assume that there isn't any problems with std.string.format, and that I have some sort of memory error somewhere.
Jun 18 2007
Alright, I don't know if I can assume this anymore. I've replaced the std.string.split call with this function (that pre-allocates the array), and I can't get the app to segfault anymore. char[][] split(char[] data) { char[][] rtn; int lastPos = 0; int index = 0; int numSpaces = std.string.count(data, " "); rtn = new char[][numSpaces + 1]; if (numSpaces > 0) { for (int i = 0; i < data.length; i++) { if (data[i] == ' ') { char[] word = data[lastPos .. i]; rtn[index++] ~= data[lastPos .. i]; lastPos = i + 1; } } } rtn[index] = data[lastPos .. data.length]; return rtn; } If I switch back to std.string.split, it dies in _d_arrayappendcT within seconds with 200 threads going on a dual-core system. I'm also able to get it to segfault if I modify the above function to do array appends instead of pre-allocating the result. I'm a bit at loss here, and starting to feel really uncomfortable with array appends at this point in a multi-threaded app. Jeff Davey Wrote:I guess I'll assume that there isn't any problems with std.string.format, and that I have some sort of memory error somewhere.
Jun 19 2007
Ack, I pasted the wrong function (that one was a result of some debugging). Here's the right one: char[][] split(char[] data) { char[][] rtn; int lastPos = 0; int index = 0; int numSpaces = std.string.count(data, " "); rtn = new char[][numSpaces + 1]; if (numSpaces > 0) { for (int i = 0; i < data.length; i++) { if (data[i] == ' ') { rtn[index++] = data[lastPos .. i]; lastPos = i + 1; } } } rtn[index] = data[lastPos .. data.length]; return rtn; } There might still be some issues with something else local, but I'm finding it very strange that replacing std.string.split with that function, I'm no longer segfaulting.
Jun 19 2007
Jeff Davey wrote:There might still be some issues with something else local, but I'm finding it very strange that replacing std.string.split with that function, I'm no longer segfaulting.Same here. Sean
Jun 29 2007