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 */
#define UHUB_EVENT_BROADCAST 0x2000
/* Shutdown hub */
#define UHUB_EVENT_HUB_SHUTDOWN 0x3001
/* Statistics, OOM, reconfigure */
#define UHUB_EVENT_STATISTICS 0x4000
#define UHUB_EVENT_OUT_OF_MEMORY 0x4001
#define UHUB_EVENT_RECONFIGURE 0x4002
#endif /* HAVE_UHUB_EVENT_ID_H */

View File

@ -104,10 +104,9 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
on_login_failure(hub, u, status_msg_hub_disabled);
return -1;
}
while (arg)
{
if (strlen(arg) == 6)
{
fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]);
@ -133,7 +132,7 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
hub_free(arg);
arg = adc_msg_get_argument(cmd, index);
}
if (u->state == state_protocol)
{
if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
@ -150,7 +149,7 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
ret = -1;
}
}
return ret;
}
@ -400,7 +399,20 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
user_destroy(user);
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:
/* FIXME: ignored */
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);
}
#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_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method());
server_tcp = net_socket_create(af, SOCK_STREAM, IPPROTO_TCP);
if (server_tcp == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
return 0;
}
@ -474,7 +472,6 @@ struct hub_info* hub_start_service(struct hub_config* config)
ret = net_set_reuseaddress(server_tcp, 1);
if (ret == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
return 0;
@ -483,7 +480,6 @@ struct hub_info* hub_start_service(struct hub_config* config)
ret = net_set_nonblocking(server_tcp, 1);
if (ret == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
return 0;
@ -493,7 +489,6 @@ struct hub_info* hub_start_service(struct hub_config* config)
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()));
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
return 0;
@ -503,7 +498,6 @@ struct hub_info* hub_start_service(struct hub_config* config)
if (ret == -1)
{
LOG_FATAL("hub_start_service(): Unable to listen to socket");
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
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_base_set(hub->evbase, &hub->ev_accept);
event_base_set(net_get_evbase(), &hub->ev_accept);
if (event_add(&hub->ev_accept, NULL) == -1)
{
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)
{
LOG_TRACE("hub_shutdown_service()");
LOG_DEBUG("hub_shutdown_service()");
event_queue_shutdown(hub->queue);
event_del(&hub->ev_accept);
net_close(hub->fd_tcp);
uman_shutdown(hub);
hub->status = hub_status_stopped;
event_base_free(hub->evbase);
hub_free(hub->sendbuf);
hub_free(hub->recvbuf);
hub_chat_history_clear(hub);
@ -959,27 +952,6 @@ size_t hub_get_min_hubs_op(struct hub_info* hub)
return hub->config->limit_min_hubs_op;
}
void hub_event_loop(struct hub_info* hub)
{
int ret;
do
{
ret = event_base_loop(hub->evbase, EVLOOP_ONCE);
if (ret != 0)
{
LOG_DEBUG("event_base_loop returned: %d", (int) ret);
}
if (ret < 0)
break;
event_queue_process(hub->queue);
}
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;
@ -988,12 +960,69 @@ void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user)
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)
{
int ret;
do
{
ret = event_base_loop(net_get_evbase(), EVLOOP_ONCE);
if (ret != 0)
{
LOG_DEBUG("event_base_loop returned: %d", (int) ret);
}
if (ret < 0)
break;
event_queue_process(hub->queue);
}
while (hub->status == hub_status_running || hub->status == hub_status_disabled);
if (hub->status == hub_status_shutdown)
{
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)
{
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);
need_notify = user_is_logged_in(user);
need_notify = user_is_logged_in(user) && hub->status == hub_status_running;
user->quit_reason = reason;
user_set_state(user, state_cleanup);

View File

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

View File

@ -81,7 +81,7 @@ void setup_signal_handlers(struct hub_info* hub)
for (i = 0; signals[i]; i++)
{
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))
{
LOG_ERROR("Error setting signal handler %d", signals[i]);
@ -147,7 +147,7 @@ int main_loop()
acl_shutdown(&acl);
free_config(&configuration);
} while(hub->status != hub_status_shutdown);
} while (hub->status == hub_status_restart);
#ifndef WIN32
shutdown_signal_handlers(hub);

View File

@ -62,9 +62,6 @@ void user_destroy(struct hub_user* 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_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 };
uman_update_stats(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);
}
#endif
@ -108,10 +108,10 @@ int uman_init(struct hub_info* hub)
hub->users = users;
#ifdef USERMANAGER_TIMER
if (hub->evbase)
if (net_get_evbase())
{
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);
}
#endif // 0
@ -126,7 +126,7 @@ int uman_shutdown(struct hub_info* hub)
#ifdef USERMANAGER_TIMER
if (evtimer_pending(&hub->ev_timer, 0))
event_del(&hub->ev_timer);
evtimer_del(&hub->ev_timer);
#endif
if (hub->users->list)

View File

@ -27,7 +27,7 @@ struct hub_user_manager
struct sid_pool* sids;
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." */
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);
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);
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)
{
if (!event_pending(&con->event, EV_READ | EV_WRITE, 0))
return;
event_del(&con->event);
if (event_pending(&con->event, EV_READ | EV_WRITE, 0))
{
event_del(&con->event);
}
net_con_clear_timeout(con);
net_close(con->sd);
con->sd = -1;
}
@ -291,7 +294,7 @@ void net_con_set_timeout(struct net_connection* con, int seconds)
{
struct timeval timeout = { seconds, 0 };
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);
}

View File

@ -21,6 +21,7 @@
static int is_ipv6_supported = -1; /* -1 = CHECK, 0 = NO, 1 = YES */
static int net_initialized = 0;
static struct event_base* net_evbase = 0;
static struct net_statistics stats;
static struct net_statistics stats_total;
@ -35,6 +36,7 @@ int net_initialize()
{
if (!net_initialized)
{
LOG_TRACE("Initializing network monitor.");
#ifdef WINSOCK
struct WSAData wsa;
@ -45,7 +47,18 @@ int net_initialize()
}
#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();
#ifdef SSL_SUPPORT
@ -83,6 +96,9 @@ int net_destroy()
{
LOG_TRACE("Shutting down network monitor");
event_base_free(net_evbase);
net_evbase = 0;
#ifdef SSL_SUPPORT
/* FIXME: Shutdown OpenSSL here. */
#endif
@ -96,6 +112,11 @@ int net_destroy()
return -1;
}
struct event_base* net_get_evbase()
{
return net_evbase;
}
static void net_error_out(int fd, const char* func)
{
int err = net_error();

View File

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