[MEDIUM] stream-interface: add a ->release callback

When a connection is closed on a stream interface, some iohandlers
will need to be informed in order to release some resources. This
normally happens upon a shutr+shutw. It is the equivalent of the
fd_delete() call which is done for real sockets, except that this
time we release internal resources.

It can also be used with real sockets because it does not cost
anything else and might one day be useful.
This commit is contained in:
Willy Tarreau 2010-07-02 11:18:03 +02:00
parent e8f6338c5d
commit 0bd05eaf24
4 changed files with 21 additions and 0 deletions

View File

@ -100,6 +100,7 @@ struct stream_interface {
void (*chk_snd)(struct stream_interface *);/* chk_snd function */
int (*connect)(struct stream_interface *, struct proxy *, struct server *,
struct sockaddr *, struct sockaddr *); /* connect function if any */
void (*release)(struct stream_interface *); /* handler to call after the last close() */
void (*iohandler)(struct stream_interface *); /* internal I/O handler when embedded */
struct buffer *ib, *ob; /* input and output buffers */
int conn_retries; /* number of connect retries left */

View File

@ -139,6 +139,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
s->si[0].err_loc = NULL;
s->si[0].connect = NULL;
s->si[0].iohandler = NULL;
s->si[0].release = NULL;
s->si[0].exp = TICK_ETERNITY;
s->si[0].flags = SI_FL_NONE;
@ -161,6 +162,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
s->si[1].err_loc = NULL;
s->si[1].connect = NULL;
s->si[1].iohandler = NULL;
s->si[1].release = NULL;
s->si[1].shutr = stream_int_shutr;
s->si[1].shutw = stream_int_shutw;
s->si[1].exp = TICK_ETERNITY;
@ -434,6 +436,9 @@ int sess_update_st_con_tcp(struct session *s, struct stream_interface *si)
si->flags &= ~SI_FL_CAP_SPLICE;
fd_delete(si->fd);
if (si->release)
si->release(si);
if (si->err_type)
return 0;

View File

@ -178,6 +178,9 @@ void stream_int_shutr(struct stream_interface *si)
si->exp = TICK_ETERNITY;
}
if (si->release)
si->release(si);
/* note that if the task exist, it must unregister itself once it runs */
if (!(si->flags & SI_FL_DONT_WAKE) && si->owner)
task_wakeup(si->owner, TASK_WOKEN_IO);
@ -214,6 +217,9 @@ void stream_int_shutw(struct stream_interface *si)
si->exp = TICK_ETERNITY;
}
if (si->release)
si->release(si);
/* note that if the task exist, it must unregister itself once it runs */
if (!(si->flags & SI_FL_DONT_WAKE) && si->owner)
task_wakeup(si->owner, TASK_WOKEN_IO);
@ -289,6 +295,7 @@ struct task *stream_int_register_handler(struct stream_interface *si,
si->chk_snd = stream_int_chk_snd;
si->connect = NULL;
si->iohandler = fct;
si->release = NULL;
si->flags |= SI_FL_WAIT_DATA;
return si->owner;
}
@ -312,6 +319,7 @@ struct task *stream_int_register_handler_task(struct stream_interface *si,
si->chk_snd = stream_int_chk_snd;
si->connect = NULL;
si->iohandler = NULL; /* not used when running as an external task */
si->release = NULL;
si->flags |= SI_FL_WAIT_DATA;
t = task_new();
@ -337,6 +345,7 @@ void stream_int_unregister_handler(struct stream_interface *si)
task_free(si->owner);
}
si->iohandler = NULL;
si->release = NULL;
si->owner = NULL;
}

View File

@ -875,6 +875,9 @@ void stream_sock_shutw(struct stream_interface *si)
si->exp = TICK_ETERNITY;
return;
}
if (si->release)
si->release(si);
}
/*
@ -899,6 +902,9 @@ void stream_sock_shutr(struct stream_interface *si)
fd_delete(si->fd);
si->state = SI_ST_DIS;
si->exp = TICK_ETERNITY;
if (si->release)
si->release(si);
return;
}
EV_FD_CLR(si->fd, DIR_RD);