what's the exactly meaning of EV_TIMEOUT in libevent? - timeout

In Programming with Libevent book, it says:
EV_TIMEOUT
This flag indicates an event that becomes active after a timeout
elapses.
AFAIK, an event associate with socket fd will become active when network IO event is ready, which is notified by select/epoll/poll/kqueue.
If EV_TIMEOUT make an event active, while the socket fd is not ready, will event_base do the callback ?
Or the socket fd is ready, while EV_TIMEOUT is not, will event_base do the callback ?

Oh, I understand.
void (*event_callback_fn)(evutil_socket_t, short, void *);
The short flag will tell callback what happened exactly.
When timeout, short & EV_TIMEOUT == true, when socket is ready, short & (EV_READ | EV_WRITE) == true.

Related

Is NSStream.close() synchronous wrt TCP?

I have input and output NSStream's as part of a TCP connection after using NSStream.getStreamsToHostWithName(). If I call the close() method on those input and output streams, then by the time the functions return, will my TCP connection be in the CLOSED state?
If not, how could I determine the time at which the underlying TCP connection actually closes?
Closing the stream terminates the flow of bytes and releases system
resources that were reserved for the stream when it was opened. If the
stream has been scheduled on a run loop, closing the stream implicitly
removes the stream from the run loop. A stream that is closed can
still be queried for its properties.
var streamStatus: NSStreamStatus { get }
The receiver’s status
enum NSStreamStatus : UInt {
case NotOpen
case Opening
case Open
case Reading
case Writing
case AtEnd
case Closed
case Error
}
As far as I can tell, the answer is no, the TCP connection will not necessarily be in the CLOSED state. To make sure the TCP connection does a graceful close and find out when that happens, one must use a lower-level API than NSStream.

libevent : whether event can be triggered if the related socket is closed by local program

if I add an event for a connection socket which is returned by accept(), as below
event_set(&conn_ev, connfd, EV_READ|EV_PERSIST, on_recv, NULL);
event_base_set(base, &conn_ev);
event_add(&conn_ev, NULL);
if at sometime, the local program(not the peer) closes the socket, will the conn_ev be triggered?
if so, how to detect whether whether the event is due to the closing of the socket?
is it recv(connfd,..) returns -1 and errno is set EBAD or any other cases?
thanks!
All sockets are marked as readable if the socket is nicely closed by the other end, with read returning zero. When an error is received they are marked either read- or write-able, with read or write returning -1.
See e.g. the socket(7) manual page for a table of states.

How to send data immediately in epoll ET mode when connect established

My server needs to send data when client connects to it. I am using Epoll ET mode.
But how to do it? Could any one give me a simple example for me?
Assuming you are listening on your socket (socket, bind, listen), and have added it's descriptor to epoll (epoll_create and epoll_ctl), then epoll_wait will tell you when there is a new connection to accept.
First you accept the connection (sockfd is descriptor of socket you're listening on, efd is epoll instance) and add it to your epoll instance:
int connfd = accept4(sockfd, NULL, 0, SOCK_NONBLOCK);
struct epoll_event ev;
ev.events = EPOLLOUT | EPOLLET;
ev.data.fd = connfd;
epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &ev)
Then you go back to your main loop and call epoll_wait again. It will tell you when the socket is ready for writing, and you just happily write or sendfile away.
Add lots of error checking, and probably TCP_CORK and you're done. There's a working example on github.com/grahamking/netshare/.
I hope this gives you enough information to get started.

epoll behavior when writing to a file descriptor

I'm using epoll to write large messages to a server using HTTP protocol. The fds are all set to non-blocking and I'm using edge-triggered events. I know for EPOLLIN I need to loop over reading the fd until EAGAIN is returned. For writing I am unsure if I should keep looping once I get EAGAIN or should I wait for epoll to notify when the fd is available for read again.
For instance, I am writing a 20K message, and on the first ::write attempt the amount of data sent = 13K. The next attempt to write returns a retVal = -1 and errno = EAGAIN.
At this point should I continue looping in a while(1) until I can write the data or should I wait for epoll to invoke my call back when the FD is ready for writing again. My understanding is that since the fd is registered for writing, epoll should notify me when the FD is ready for writing again. But that doesn't seem to be happening in my program.
Do I need to set a special flag or modify the FD to get the notification?
At this point should I continue looping in a while(1) until I can write the data
No!
or should I wait for epoll to invoke my call back when the FD is ready for writing again.
Yes, you should (but what callback? epoll_wait doesn't have a callback mechanism, it just returns)
My understanding is that since the fd is registered for writing, epoll should notify me when the FD is ready for writing again. But that doesn't seem to be happening in my program.
If the FD is registered with EPOLLOUT or EPOLLIN | EPOLLOUT, it should indeed. Could you provide a small example demonstrating the problem?

how to manage EINTR errno in sem_timedwait

Can you help me to understand why it is recommended to use:
while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
continue; // Restart when interrupted by handler
(EINTR: The call was interrupted by a signal handler)
Instead of simply:
s = sem_timedwait(&sem, &ts);
In witch cases I have to manage EINTR ?
The loop will cause the system call to be restarted if a signal is caught during the execution of the system call, so it will not go on to the next statement unless the system call has either succeeded or failed (with some other error). Otherwise the thread will continue execution with the next statement when the system call is interrupted by a signal handler.
For example, if you want to be able to abort this sem_timedwait() by sending a particular signal to the thread, then you would not want to unconditionally restart the system call. Instead you may want to mark that the operation was aborted and clean up. If you have multiple signal handlers, the signal handler can set a flag which can be checked when EINTR is encountered in order to determine whether to restart the system call.
This only matters if the thread catches any signals using a signal handler, and the sigaction() SA_RESTART flag was not used to automatically restart any interrupted system call. However, if you are not using any signal handlers and did not intend for your code to be affected by a signal handler, it is still good practice to use the loop so that it will continue to work as you intended even if your code is later used in the same program as other code which uses signal handlers for unrelated purposes.

Resources