Fixes to shutdown...

This commit is contained in:
Jan Vidar Krey 2009-08-03 23:59:02 +02:00
parent fbe98d6011
commit eca0f931bd
10 changed files with 120 additions and 65 deletions

View File

@ -28,10 +28,14 @@
/* Send a broadcast message */ /* Send a broadcast message */
#define UHUB_EVENT_BROADCAST 0x2000 #define UHUB_EVENT_BROADCAST 0x2000
/* Shutdown hub */
#define UHUB_EVENT_HUB_SHUTDOWN 0x3001
/* Statistics, OOM, reconfigure */ /* Statistics, OOM, reconfigure */
#define UHUB_EVENT_STATISTICS 0x4000 #define UHUB_EVENT_STATISTICS 0x4000
#define UHUB_EVENT_OUT_OF_MEMORY 0x4001 #define UHUB_EVENT_OUT_OF_MEMORY 0x4001
#define UHUB_EVENT_RECONFIGURE 0x4002 #define UHUB_EVENT_RECONFIGURE 0x4002
#endif /* HAVE_UHUB_EVENT_ID_H */ #endif /* HAVE_UHUB_EVENT_ID_H */

View File

@ -107,7 +107,6 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
while (arg) while (arg)
{ {
if (strlen(arg) == 6) if (strlen(arg) == 6)
{ {
fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]); fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]);
@ -401,6 +400,19 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
break; break;
} }
case UHUB_EVENT_HUB_SHUTDOWN:
{
struct hub_user* u = (struct hub_user*) list_get_first(hub->users->list);
while (u)
{
uman_remove(hub, u);
user_destroy(u);
u = (struct hub_user*) list_get_first(hub->users->list);
}
break;
}
default: default:
/* FIXME: ignored */ /* FIXME: ignored */
break; break;
@ -448,25 +460,11 @@ struct hub_info* hub_start_service(struct hub_config* config)
net_address_to_string(AF_INET6, &((struct sockaddr_in6*) &addr)->sin6_addr, address_buf, INET6_ADDRSTRLEN); net_address_to_string(AF_INET6, &((struct sockaddr_in6*) &addr)->sin6_addr, address_buf, INET6_ADDRSTRLEN);
} }
#ifdef LIBEVENT_1_4
hub->evbase = event_base_new();
#else
hub->evbase = event_init();
#endif
if (!hub->evbase)
{
LOG_ERROR("Unable to initialize libevent.");
hub_free(hub);
return 0;
}
LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", address_buf, config->server_port); LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", address_buf, config->server_port);
LOG_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method());
server_tcp = net_socket_create(af, SOCK_STREAM, IPPROTO_TCP); server_tcp = net_socket_create(af, SOCK_STREAM, IPPROTO_TCP);
if (server_tcp == -1) if (server_tcp == -1)
{ {
event_base_free(hub->evbase);
hub_free(hub); hub_free(hub);
return 0; return 0;
} }
@ -474,7 +472,6 @@ struct hub_info* hub_start_service(struct hub_config* config)
ret = net_set_reuseaddress(server_tcp, 1); ret = net_set_reuseaddress(server_tcp, 1);
if (ret == -1) if (ret == -1)
{ {
event_base_free(hub->evbase);
hub_free(hub); hub_free(hub);
net_close(server_tcp); net_close(server_tcp);
return 0; return 0;
@ -483,7 +480,6 @@ struct hub_info* hub_start_service(struct hub_config* config)
ret = net_set_nonblocking(server_tcp, 1); ret = net_set_nonblocking(server_tcp, 1);
if (ret == -1) if (ret == -1)
{ {
event_base_free(hub->evbase);
hub_free(hub); hub_free(hub);
net_close(server_tcp); net_close(server_tcp);
return 0; return 0;
@ -493,7 +489,6 @@ struct hub_info* hub_start_service(struct hub_config* config)
if (ret == -1) if (ret == -1)
{ {
LOG_FATAL("hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error())); LOG_FATAL("hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error()));
event_base_free(hub->evbase);
hub_free(hub); hub_free(hub);
net_close(server_tcp); net_close(server_tcp);
return 0; return 0;
@ -503,7 +498,6 @@ struct hub_info* hub_start_service(struct hub_config* config)
if (ret == -1) if (ret == -1)
{ {
LOG_FATAL("hub_start_service(): Unable to listen to socket"); LOG_FATAL("hub_start_service(): Unable to listen to socket");
event_base_free(hub->evbase);
hub_free(hub); hub_free(hub);
net_close(server_tcp); net_close(server_tcp);
return 0; return 0;
@ -549,7 +543,7 @@ struct hub_info* hub_start_service(struct hub_config* config)
} }
event_set(&hub->ev_accept, hub->fd_tcp, EV_READ | EV_PERSIST, net_on_accept, hub); event_set(&hub->ev_accept, hub->fd_tcp, EV_READ | EV_PERSIST, net_on_accept, hub);
event_base_set(hub->evbase, &hub->ev_accept); event_base_set(net_get_evbase(), &hub->ev_accept);
if (event_add(&hub->ev_accept, NULL) == -1) if (event_add(&hub->ev_accept, NULL) == -1)
{ {
uman_shutdown(hub); uman_shutdown(hub);
@ -601,14 +595,13 @@ struct hub_info* hub_start_service(struct hub_config* config)
void hub_shutdown_service(struct hub_info* hub) void hub_shutdown_service(struct hub_info* hub)
{ {
LOG_TRACE("hub_shutdown_service()"); LOG_DEBUG("hub_shutdown_service()");
event_queue_shutdown(hub->queue); event_queue_shutdown(hub->queue);
event_del(&hub->ev_accept); event_del(&hub->ev_accept);
net_close(hub->fd_tcp); net_close(hub->fd_tcp);
uman_shutdown(hub); uman_shutdown(hub);
hub->status = hub_status_stopped; hub->status = hub_status_stopped;
event_base_free(hub->evbase);
hub_free(hub->sendbuf); hub_free(hub->sendbuf);
hub_free(hub->recvbuf); hub_free(hub->recvbuf);
hub_chat_history_clear(hub); hub_chat_history_clear(hub);
@ -959,13 +952,51 @@ size_t hub_get_min_hubs_op(struct hub_info* hub)
return hub->config->limit_min_hubs_op; return hub->config->limit_min_hubs_op;
} }
void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user)
{
struct event_data post;
memset(&post, 0, sizeof(post));
post.id = UHUB_EVENT_USER_DESTROY;
post.ptr = user;
event_queue_post(hub->queue, &post);
net_con_close(&user->net.connection);
if (user->id.sid)
{
sid_free(hub->users->sids, user->id.sid);
}
}
void hub_disconnect_all(struct hub_info* hub)
{
struct event_data post;
memset(&post, 0, sizeof(post));
post.id = UHUB_EVENT_HUB_SHUTDOWN;
post.ptr = 0;
event_queue_post(hub->queue, &post);
}
void hub_schedule_destroy_all(struct hub_info* hub)
{
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{
hub_schedule_destroy_user(hub, user);
user = (struct hub_user*) list_get_next(hub->users->list);
}
}
void hub_event_loop(struct hub_info* hub) void hub_event_loop(struct hub_info* hub)
{ {
int ret; int ret;
do do
{ {
ret = event_base_loop(hub->evbase, EVLOOP_ONCE); ret = event_base_loop(net_get_evbase(), EVLOOP_ONCE);
if (ret != 0) if (ret != 0)
{ {
@ -978,22 +1009,20 @@ void hub_event_loop(struct hub_info* hub)
event_queue_process(hub->queue); event_queue_process(hub->queue);
} }
while (hub->status == hub_status_running || hub->status == hub_status_disabled); while (hub->status == hub_status_running || hub->status == hub_status_disabled);
}
void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user)
{
struct event_data post;
memset(&post, 0, sizeof(post));
post.id = UHUB_EVENT_USER_DESTROY;
post.ptr = user;
event_queue_post(hub->queue, &post);
if (user->id.sid) if (hub->status == hub_status_shutdown)
{ {
sid_free(hub->users->sids, user->id.sid); LOG_DEBUG("Removing all users...");
event_queue_process(hub->queue);
event_queue_process(hub->queue);
hub_disconnect_all(hub);
event_queue_process(hub->queue);
hub->status = hub_status_stopped;
} }
} }
void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason) void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason)
{ {
struct event_data post; struct event_data post;
@ -1010,7 +1039,7 @@ void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason
LOG_TRACE("hub_disconnect_user(), user=%p, reason=%d, state=%d", user, reason, user->state); LOG_TRACE("hub_disconnect_user(), user=%p, reason=%d, state=%d", user, reason, user->state);
need_notify = user_is_logged_in(user); need_notify = user_is_logged_in(user) && hub->status == hub_status_running;
user->quit_reason = reason; user->quit_reason = reason;
user_set_state(user, state_cleanup); user_set_state(user, state_cleanup);

View File

@ -95,7 +95,6 @@ struct hub_info
struct event ev_timer; struct event ev_timer;
struct hub_stats stats; struct hub_stats stats;
struct event_queue* queue; struct event_queue* queue;
struct event_base* evbase;
struct hub_config* config; struct hub_config* config;
struct hub_user_manager* users; struct hub_user_manager* users;
struct acl_handle* acl; struct acl_handle* acl;

View File

@ -81,7 +81,7 @@ void setup_signal_handlers(struct hub_info* hub)
for (i = 0; signals[i]; i++) for (i = 0; signals[i]; i++)
{ {
signal_set(&signal_events[i], signals[i], hub_handle_signal, hub); signal_set(&signal_events[i], signals[i], hub_handle_signal, hub);
event_base_set(hub->evbase, &signal_events[i]); event_base_set(net_get_evbase(), &signal_events[i]);
if (signal_add(&signal_events[i], NULL)) if (signal_add(&signal_events[i], NULL))
{ {
LOG_ERROR("Error setting signal handler %d", signals[i]); LOG_ERROR("Error setting signal handler %d", signals[i]);
@ -147,7 +147,7 @@ int main_loop()
acl_shutdown(&acl); acl_shutdown(&acl);
free_config(&configuration); free_config(&configuration);
} while(hub->status != hub_status_shutdown); } while (hub->status == hub_status_restart);
#ifndef WIN32 #ifndef WIN32
shutdown_signal_handlers(hub); shutdown_signal_handlers(hub);

View File

@ -62,9 +62,6 @@ void user_destroy(struct hub_user* user)
{ {
LOG_TRACE("user_destroy(), user=%p", user); LOG_TRACE("user_destroy(), user=%p", user);
net_con_close(&user->net.connection);
net_con_clear_timeout(&user->net.connection);
hub_recvq_destroy(user->net.recv_queue); hub_recvq_destroy(user->net.recv_queue);
hub_sendq_destroy(user->net.send_queue); hub_sendq_destroy(user->net.send_queue);

View File

@ -77,7 +77,7 @@ static void timer_statistics(int fd, short ev, void *arg)
struct timeval timeout = { TIMEOUT_STATS, 0 }; struct timeval timeout = { TIMEOUT_STATS, 0 };
uman_update_stats(hub); uman_update_stats(hub);
evtimer_set(&hub->ev_timer, timer_statistics, hub); evtimer_set(&hub->ev_timer, timer_statistics, hub);
event_base_set(hub->evbase, &hub->ev_timer); event_base_set(net_get_evbase(), &hub->ev_timer);
evtimer_add(&hub->ev_timer, &timeout); evtimer_add(&hub->ev_timer, &timeout);
} }
#endif #endif
@ -108,10 +108,10 @@ int uman_init(struct hub_info* hub)
hub->users = users; hub->users = users;
#ifdef USERMANAGER_TIMER #ifdef USERMANAGER_TIMER
if (hub->evbase) if (net_get_evbase())
{ {
evtimer_set(&hub->ev_timer, timer_statistics, hub); evtimer_set(&hub->ev_timer, timer_statistics, hub);
event_base_set(hub->evbase, &hub->ev_timer); event_base_set(net_get_evbase(), &hub->ev_timer);
evtimer_add(&hub->ev_timer, &timeout); evtimer_add(&hub->ev_timer, &timeout);
} }
#endif // 0 #endif // 0
@ -126,7 +126,7 @@ int uman_shutdown(struct hub_info* hub)
#ifdef USERMANAGER_TIMER #ifdef USERMANAGER_TIMER
if (evtimer_pending(&hub->ev_timer, 0)) if (evtimer_pending(&hub->ev_timer, 0))
event_del(&hub->ev_timer); evtimer_del(&hub->ev_timer);
#endif #endif
if (hub->users->list) if (hub->users->list)

View File

@ -27,7 +27,7 @@ struct hub_user_manager
struct sid_pool* sids; struct sid_pool* sids;
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */ uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */ uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
struct linked_list* list; /**<< "Contains all users" */ struct linked_list* list; /**<< "Contains all logged in users" */
}; };
/** /**

View File

@ -107,7 +107,7 @@ void net_con_initialize(struct net_connection* con, int sd, struct ip_addr_encap
if (events & EV_WRITE) net_con_flag_set(con, NET_WANT_WRITE); if (events & EV_WRITE) net_con_flag_set(con, NET_WANT_WRITE);
event_set(&con->event, con->sd, events | EV_PERSIST, net_con_event, con); event_set(&con->event, con->sd, events | EV_PERSIST, net_con_event, con);
event_base_set(g_hub->evbase, &con->event); event_base_set(net_get_evbase(), &con->event);
event_add(&con->event, 0); event_add(&con->event, 0);
net_set_nonblocking(sd, 1); net_set_nonblocking(sd, 1);
@ -134,9 +134,12 @@ void net_con_update(struct net_connection* con, int events)
void net_con_close(struct net_connection* con) void net_con_close(struct net_connection* con)
{ {
if (!event_pending(&con->event, EV_READ | EV_WRITE, 0)) if (event_pending(&con->event, EV_READ | EV_WRITE, 0))
return; {
event_del(&con->event); event_del(&con->event);
}
net_con_clear_timeout(con);
net_close(con->sd); net_close(con->sd);
con->sd = -1; con->sd = -1;
} }
@ -291,7 +294,7 @@ void net_con_set_timeout(struct net_connection* con, int seconds)
{ {
struct timeval timeout = { seconds, 0 }; struct timeval timeout = { seconds, 0 };
evtimer_set(&con->timeout, net_con_event, con); evtimer_set(&con->timeout, net_con_event, con);
event_base_set(g_hub->evbase, &con->timeout); event_base_set(net_get_evbase(), &con->timeout);
evtimer_add(&con->timeout, &timeout); evtimer_add(&con->timeout, &timeout);
} }

View File

@ -21,6 +21,7 @@
static int is_ipv6_supported = -1; /* -1 = CHECK, 0 = NO, 1 = YES */ static int is_ipv6_supported = -1; /* -1 = CHECK, 0 = NO, 1 = YES */
static int net_initialized = 0; static int net_initialized = 0;
static struct event_base* net_evbase = 0;
static struct net_statistics stats; static struct net_statistics stats;
static struct net_statistics stats_total; static struct net_statistics stats_total;
@ -35,6 +36,7 @@ int net_initialize()
{ {
if (!net_initialized) if (!net_initialized)
{ {
LOG_TRACE("Initializing network monitor.");
#ifdef WINSOCK #ifdef WINSOCK
struct WSAData wsa; struct WSAData wsa;
@ -45,7 +47,18 @@ int net_initialize()
} }
#endif /* WINSOCK */ #endif /* WINSOCK */
LOG_TRACE("Initializing network monitor."); #ifdef LIBEVENT_1_4
net_evbase = event_base_new();
#else
net_evbase = event_init();
#endif
if (!net_evbase)
{
LOG_ERROR("Unable to initialize libevent.");
return 0;
}
LOG_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method());
net_stats_initialize(); net_stats_initialize();
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
@ -83,6 +96,9 @@ int net_destroy()
{ {
LOG_TRACE("Shutting down network monitor"); LOG_TRACE("Shutting down network monitor");
event_base_free(net_evbase);
net_evbase = 0;
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
/* FIXME: Shutdown OpenSSL here. */ /* FIXME: Shutdown OpenSSL here. */
#endif #endif
@ -96,6 +112,11 @@ int net_destroy()
return -1; return -1;
} }
struct event_base* net_get_evbase()
{
return net_evbase;
}
static void net_error_out(int fd, const char* func) static void net_error_out(int fd, const char* func)
{ {
int err = net_error(); int err = net_error();

View File

@ -66,6 +66,8 @@ extern int net_initialize();
*/ */
extern int net_destroy(); extern int net_destroy();
extern struct event_base* net_get_evbase();
/** /**
* @return the number of sockets currrently being monitored. * @return the number of sockets currrently being monitored.
*/ */