From 0bd05eaf2437580e1dee917706ec87aa4ed9b018 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 2 Jul 2010 11:18:03 +0200 Subject: [PATCH] [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. --- include/types/stream_interface.h | 1 + src/session.c | 5 +++++ src/stream_interface.c | 9 +++++++++ src/stream_sock.c | 6 ++++++ 4 files changed, 21 insertions(+) diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h index db166c9b2..cfba68735 100644 --- a/include/types/stream_interface.h +++ b/include/types/stream_interface.h @@ -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 */ diff --git a/src/session.c b/src/session.c index 556fffefc..10c7f13d6 100644 --- a/src/session.c +++ b/src/session.c @@ -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; diff --git a/src/stream_interface.c b/src/stream_interface.c index c45abdbe8..113f01c65 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -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; } diff --git a/src/stream_sock.c b/src/stream_sock.c index 2d5ef6d70..8cd721ea7 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -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);