Blocking sockets

While read() is blocking and waitting data from the socket is there any problems to write() the same socket from another thread at the same time?

I tried it and it seems that it’s ok but if anybody knows that this is not ok please educate me.

Charlie is right, but you can easily get around that by using the tc() functions. Don’t wait for a char, just ask if one is in the buffer.

-Erik

=========================================
struct serial_buffer_t sbt;
tcgetbuffers(fds, &sbt);

if( sbt.rxbuf > 0 )
{
read(fds, buf, _countof(buf));
}

Thank you very much for the answers.

But I mean reading and writing from/to sockets (TCP/IP)?

NET+OS will only allow one thread at a time to have control of the serial driver. I.E. if one thread is doing a blocking read/write, and a second thread comes in, it should be returned an access error.

That’s strange, because I have a thread permanently reading one character from serial port (sets an event when received and loops back to read) and I am writing to same serial port from other thread with no problem!

If you’re using send() and recv() to talk to a socket, you can do so from multiple threads, but these are not thread safe, so you will want to use a Mutex or Semaphore. Similar to what Erik posted, you can use select() to determine if you need to read from the socket before actually calling recv().

I have a thread which is in blocking recv() and another is writing by the write().

This is working for me without any errors (or do they come in stage later…?!)

So you mean that the recv() and write() functions itself for the socket is not a thread safe for example I cannot call write() from multiple threads at the same time without using semaphores but I can call write() from one thread and recv() from another at the same time as my example code is showing me.

Right?

I mean I am writing the socket by the send() command and reading by the recv()…

While it is supposedly fixed in NetOS 7, all the network functions are unsafe to simultaneously use in more than one thread at a time in 6.x. In other words, don’t call send(), recv(), or select() at the same time from two different threads.

I posted a patch for this a while ago.

http://www.digi.com/support/forum/viewthread_thread,1408#5227

Ok.

Im using 7.1 and as I said it seems to work ok. I can use send() without any errors while another thread is in blocking recv().

Just asked this to solve out is there any known “hidden problems” which comes out later if used like this…

I’m not sure when select was fixed, but it definately is working properly in multiple threads in NET+OS 7.1. However, sockets, are not thread safe when accessed from multiple threads at the same time. You do need to semaphore or mutex protect them.

What I meant was don’t call select() from two threads at once, or call send() from two threads at once… There never has been a problem with calling send() and recv() simultaneously.

Apparently the base code didn’t use mutexes in 6.x so if you called select() from two threads they both would never return! I spent weeks figuring that one out back in '05.

What do you mean exactly charliek?

Is it safe to do send() in one thread and recv() in another thread (at the same time)?
I’m trying to figure out which socket function calls have to be protected by mutexes. It’s hard to find things like this in the documentation, so I hope someone here can explain it.

It is not safe to call a send() and a recv() on the same socket from two different threads running at the same time. If you need to, mutex protect them (see the API -> threadx -> functions -> tx_mutex_*).

If you mutex protect them, then you cannot do a send() until recv() returns. But recv() being blocking will not return until it gets a character or string. So, you will loose the feature of sending while waiting for some character (unless you use a non-blocking function called repeatedly and checking for result each time).

I don’t want to mutex protect the socket because recv() can block which means and I can’t send anything until I receive something!

Also, egawtry says the socket code should be reentrant in NET+OS 7. (I’m using 7.1 by the way).

So what should I do now? I would like to get this clear during my design-phase, before I start coding.

I particularly don’t like the fact that the documentation has no information about this, while it is very important. So you have to rely on forums, where different people tell different stories.

Question send to Online Support of Digi:
“I’m developing my own application that uses one socket and two threads. Thread A does a blocking recv() and thread B does a blocking send(), both on the same socket. Is this safe? So is the socket code reentrant/thread-safe?”

Answer from Digi:
“No, the sockets are not reentrant. You must semaphore protect them yourself. Failure to do this can result in race conditions and other bad things.”

Hmmmm, so I must work around this limitation. I’m still thinking of a way to do this.

What is your end goal? What problem are you trying to solve by running two threads accessing the same socket at the same time?

I have a single TCP connection between a PC and the DigiConnect. Sending and receiving are ‘asynchronous’ in my application. The PC and the DigiConnect can send data at any time.
To me, the most logical implementation would be to use two threads: one for reading and one for writing, both on the same socket.

Do you have an alternative?
The most easy workaround seems to create two TCP connections (two sockets). Then each thread has its own socket. What do you think?

You could actually implement this quite easily within one thread with blocking or non-blocking sockets. Use select, add your socket file description and serial file descriptor as the two descriptors to watch, and when select returns indicating that you’ve recieved data on one of the file descriptors, write it to the other file descriptor.