I'm programming an application(client/server) in C++ for linux using epoll y pthreads but I don't know how to handle the connect() calls for attach a new connection in the descriptor list if a loop with epoll_wait() is running(Edge-triggered), How to can I do it?... I could to use a dummy file descriptor to trigger an event and scape of wait?, or a simple call to connect() could fire the event??...
Sorry for my bad english...
Yes, you can use another file descriptor that's just for waking up your epoll_wait() loop. Use pipe() to create the file descriptor. Add the reading end of the pipe to your epoll list, and write a single byte to the writing end when you want to wake it up. The reading side can just read that byte and discard it.
Related
This is similar to the question 1 but is about pipes. If epoll_wait returns EPOLLERR for the write end of a pipe, how do I distinguish a general error condition from the read end of the pipe been closed? For the sockets case the answer was to use "use getsockopt and SO_ERROR to get the pending error" and compare that with EPIPE. But what API should I use for the pipe as the pipe created by pipe(2) on Linux or returned by opening a named pipe is not a socket?
Other than the other end being closed, there aren't any errors on a write end of a pipe which could be detected by epoll. The few errors that are possible on an actual call to write() could not be known in advance (e.g., if you pass an invalid buffer pointer), so epoll cannot detect them. Therefore, if epoll tells you there's an error, it is EPIPE.
(OK, there is actually another possible error condition, but it can be triggered only by a programming error: if you close the file descriptor and then use epoll_wait while it is on the list - I don't know how epoll will react to that).
I'm writing to a file (a writable steam) and I need to close the file once I'm done. I'm not sure of the difference between these two functions or if I need to call them both. Here's what the documentation says:
stream.end()
Terminates the stream with EOF or FIN. This call will allow queued write data to be sent before closing the stream.
stream.destroySoon()
After the write queue is drained, close the file descriptor. destroySoon() can still destroy straight away, as long as there is no data left in the queue for writes.
There is no difference.
From fs.js in the node source:
// There is no shutdown() for files.
WriteStream.prototype.destroySoon = WriteStream.prototype.end;
I'm using epoll_create to wait on a socket.
What is the life-cycle of the returned resource tied to? Is there something like an epoll_destroy or is it tied to the socket's close or destory call?
Can I re-use the result of epoll_create if close my socket and re-open a new one. Or should I just call epoll_create and forget about the previous result of epoll_create.
epoll_create(2) returns a file descriptor, so you just use close(2) on it when done.
Then, the idea of I/O multiplexing, often called Asynchronous I/O, is to wait for multiple events, and handle them one at a time. That means you generally need only one polling file descriptor.
epoll(7) manual page contains basic example of suggested API usage.
I am new to linux server programming with epoll.
I have 2 threads: Thread_Accept and Thread_epoll. The former is block accept loop, if new connection is coming, it will add the new fd with epoll_ctl(). The latter is a big epoll_wait() loop.
Now my question is: What if when Thread_Accept executing epoll_ctl() while the Thread_epoll is in the middle of epoll_wait? Will it got any side effect?
Thanks in advance.
regards,
Martin
From the epoll_wait man page:
While one thread is blocked in a call to epoll_pwait(), it is possible for another thread to add a file descriptor to the waited-upon epoll instance. If the new file descriptor becomes ready, it will cause the epoll_wait() call to unblock.
So, no side effects when adding a new file descriptor :-)
(This man page note is the result of the bug mentioned by nathansizemore)
Why don't you make it one thread?
You can set the listener socket to nonblocking and add the socket to your big epoll_wait
From my experience, yes. But, this says otherwise
My application is going to send huge amount of data over network, so I decided (because I'm using Linux) to use epoll and splice. Here's how I see it (pseudocode):
epoll_ctl (file_fd, EPOLL_CTL_ADD); // waiting for EPOLLIN event
while(1)
{
epoll_wait (tmp_structure);
if (tmp_structure->fd == file_descriptor)
{
epoll_ctl (file_fd, EPOLL_CTL_DEL);
epoll_ctl (tcp_socket_fd, EPOLL_CTL_ADD); // wait for EPOLLOUT event
}
if (tmp_structure->fd == tcp_socket_descriptor)
{
splice (file_fd, tcp_socket_fd);
epoll_ctl (tcp_socket_fd, EPOLL_CTL_DEL);
epoll_ctl (file_fd, EPOLL_CTL_ADD); // waiting for EPOLLIN event
}
}
I assume, that my application will open up to 2000 TCP sockets. I want o ask you about two things:
There will be quite a lot of epoll_ctl calls, won't wit be slow when I will have so many sockets?
File descriptor has to become readable first and there will be some interval before socket will become writable. Can I be sure, that at the moment when socket becomes writable file descriptor is still readable (to avoid blocking call)?
1st question
You can use edge triggered rather then even triggered polling thus you do not have to delete socket each time.
You can use EPOLLONESHOT to prevent removing socket
File descriptor has to become readable first and there will be some interval before socket will become writable.
What kind of file descriptor? If this file on file system you can't use select/poll or other tools for this purpose, file will be always readable or writeable regardless the state if disk and cache. If you need to do staff asynchronous you may use aio_* API but generally just read from file write to file and assume it is non-blocking.
If it is TCP socket then it would be writeable most of the time. It is better to use
non-blocking calls and put sockets to epoll when you get EWOULDBLOCK.
Consider using EPOLLET flag. This is definitely for that case. When using this flag you can use event loop in a proper way without deregistering (or modifying mode on) file descriptors since first registration in epoll. :) enjoy!