I'm currently writing a simple webserver in C for a course I'm doing. One requirement is for us to implement a thread pool to handle connections using pthreads.
I know how I would go about doing this roughly(calling accept in a main thread and passing the file descriptor to a freee thread), however my friend suggested an alternate method than the one I had in mind: creating all my threads up front, and getting them all to loop forever on a call to accept. The idea being that accept will block all the idle threads and when a connection comes in, only giving the file descriptor to one. Then when a given thread is done with a connection it loops back around and blocks on a call to accept again. Using the call to accept() as a semaphore essentially. This would simplify the implementation quite a bit he figures, as you wouldn't need to keep track of which threads are busy and which are ready for a connection. It would also be lower latency in theory, as the thread can immediately start executing.
My question is, is this safe? I'm planning to implement it and try it out, but I'm not ready yet and I'm quite curious to know the answer. I've searched on google and here on stackoverflow, but couldn't find anyone doing it this way. Is accept thread safe? I assume there will be more overhead with this approach as you are running all your threads all the time, are the two approaches simply a simple memory/latency tradeoff?
Edit: I'm unsure if this should be community wiki, apologies if it should be, I can't find the button :P
The collection classes that are thread-safe in Java are Stack, Vector, Properties, Hashtable, etc.
the standard C printf() and scanf() functions use stdio so they are thread-safe.
Writing to a socket by multiple threads is thread-safe as long as the other end can make sense of the intereleaved data. Reading from a socket by multiple threads is thread-safe as long as this end can make sense of the interleaved data.
How We Achieve Thread Safety In Spring Boot? The default front controller (web server) for spring boot web application is Servlet which it creates a new separate thread for every http request. Servlet then delegates the control flow to the lower layers beginning from controller layer.
Yes. This is a common way to design multithreaded servers and accepted design practice.
You can also fork
several times and have the child processes call accept
, this will allow you to do multithreading without needing a threads library. Older servers do this.
Since this has been bountied, asking for references:
Yes, accept()
is thread-safe, as POSIX defines that term.
The relevant reference would be section 2.9.1 of POSIX.1, the current version of which says:
All functions defined by this volume of POSIX.1-2017 shall be thread-safe, except that the following functions need not be thread-safe.
[a list that does not include
accept()
]
For completeness, POSIX does define accept()
: https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html, so as a POSIX function that does not appear on the list of exceptions, POSIX specifies that it is thread-safe.
In comments, @Rick (the bounty offerer) says:
In some ways I get the point now. thread-safe would be the property that meets the behaviour. I was thinking thread-safe has to be threads within same process. But now I think there aren't much differences between threads within same process or threads between different processes. In some ways they are the same. So the concept of thread-safety can be applied to both scenarios.
The POSIX definitions regarding thread-safety do indeed refer to threads in the same process (see: §2.9).
If you are asking about what happens after fork()
, and if it is safe for the parent and child to concurrently call into accept()
, we note first that POSIX defines a system resource known as a connection indication queue. Then we note that the child of fork()
gets a copy of the parent's descriptors, and therefore the child and parent will access the same connection indication queue (just as a duplicate file descriptor to a text file would be accessing the same file).
The definition of what accept()
does for each process (child and parent) is the same at that point.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With