struct dlist *watch_list;
struct dlist *conn_cb_list;
struct dlist *disconn_cb_list;
+ struct dlist *disconn_fd_list;
enum processing_event_callback {
PROCESSING_NONE = 0x0,
PROCESSING_DISCONNECTION = 0x01,
.watch_list = NULL,
.conn_cb_list = NULL,
.disconn_cb_list = NULL,
+ .disconn_fd_list = NULL,
.processing_event_callback = PROCESSING_NONE,
};
dlist_foreach_safe(s_info.watch_list, l, n, item) {
if (item->server_fd == socket_fd) {
DbgPrint("Watch item removed: %d/%d\n", item->server_fd, item->fd);
- /*!
- * \WARN
+ /**
+ * @WARN
* If the watch_list item is removed from disconnected
* callback, this list loop can be broken.
* Please check it again.
*/
- invoke_disconn_cb_list(item->fd, 0, 0, 0);
+ (void)invoke_disconn_cb_list(item->fd, 0, 0, 0);
+ /**
+ * @note
+ * socket_fd will be closed by caller.
+ * so we do not need to close it at here.
+ */
s_info.watch_list = dlist_remove(s_info.watch_list, l);
if (item->id > 0) {
s_info.processing_event_callback &= ~PROCESSING_CONNECTION;
}
-HAPI void invoke_disconn_cb_list(int handle, int remove_id, int remove_data, int watch)
+HAPI int invoke_disconn_cb_list(int handle, int remove_id, int remove_data, int watch)
{
struct dlist *l;
struct dlist *n;
struct evtdata *cbdata;
+ void *item;
+
+ /**
+ * @note
+ * Basically, the disconnected handler will be called once.
+ * But from the disconnected callback, someone calls fini(fd),
+ * this disconnection callback can be called again.
+ * So we have to check whether this is a nested call or not.
+ * If it is a nested call, we should not do anything anymore.
+ */
+ dlist_foreach_safe(s_info.disconn_fd_list, l, n, item) {
+ if (handle == (int)((long)item)) { /*!< Cast for 64 bits */
+ DbgPrint("nested destroyer %d\n", handle);
+ return 1;
+ }
+ }
+
+ s_info.disconn_fd_list = dlist_append(s_info.disconn_fd_list, (void *)((long)handle)); /*!< Cast for 64 bits */
s_info.processing_event_callback |= PROCESSING_DISCONNECTION;
dlist_foreach_safe(s_info.disconn_cb_list, l, n, cbdata) {
- /*!
- * \NOTE
+ /**
+ * @note
* cbdata->deleted must has to be checked before call the function and
* return from the function call.
*/
ErrPrint("Failed to destroy watch item\n");
}
}
+
+ dlist_remove_data(s_info.disconn_fd_list, (void *)((long)handle)); /*!< Cast for 64 bits */
+ return 0;
}
static int validate_handle(int fd)
if (!(cond & G_IO_IN)) {
DbgPrint("Client is disconencted\n");
- invoke_disconn_cb_list(client_fd, 0, 1, 1);
+ (void)invoke_disconn_cb_list(client_fd, 0, 1, 1);
secure_socket_destroy_handle(client_fd);
return FALSE;
}
if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
DbgPrint("Client connection is lost\n");
- invoke_disconn_cb_list(client_fd, 0, 1, 1);
+ (void)invoke_disconn_cb_list(client_fd, 0, 1, 1);
secure_socket_destroy_handle(client_fd);
return FALSE;
}
ret = cbdata->service_cb(client_fd, cbdata->data);
if (ret < 0) {
DbgPrint("service callback returns %d < 0\n", ret);
- invoke_disconn_cb_list(client_fd, 0, 1, 1);
+ (void)invoke_disconn_cb_list(client_fd, 0, 1, 1);
secure_socket_destroy_handle(client_fd);
return FALSE;
}
/* Check whether the socket FD is closed or not */
if (!validate_handle(client_fd)) {
- invoke_disconn_cb_list(client_fd, 0, 1, 1);
+ (void)invoke_disconn_cb_list(client_fd, 0, 1, 1);
secure_socket_destroy_handle(client_fd);
return FALSE;
}
EAPI int com_core_server_destroy(int handle)
{
DbgPrint("Close server handle[%d]\n", handle);
- invoke_disconn_cb_list(handle, 1, 1, 1);
- secure_socket_destroy_handle(handle);
+ if (invoke_disconn_cb_list(handle, 1, 1, 1) == 0) {
+ secure_socket_destroy_handle(handle);
+ }
return 0;
}
EAPI int com_core_client_destroy(int handle)
{
DbgPrint("Close client handle[%d]\n", handle);
- invoke_disconn_cb_list(handle, 1, 1, 1);
- secure_socket_destroy_handle(handle);
+ if (invoke_disconn_cb_list(handle, 1, 1, 1) == 0) {
+ secure_socket_destroy_handle(handle);
+ }
return 0;
}
if (status != 0) {
ErrPrint("Join: %s\n", strerror(status));
} else {
- ErrPrint("Thread returns: %d\n", (int)res);
+ ErrPrint("Thread returns: %d\n", (int)((long)res));
}
dlist_foreach_safe(tcb->chunk_list, l, n, chunk) {
errout:
DbgPrint("Disconnecting\n");
- invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
+ (void)invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
terminate_thread(tcb);
tcb_destroy(tcb);
return FALSE;
}
if (ret != 0) {
ErrPrint("Thread creation failed: %s\n", strerror(ret));
- invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
+ (void)invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
secure_socket_destroy_handle(tcb->handle);
tcb_destroy(tcb);
server_destroy(server);
}
if (ret != 0) {
ErrPrint("Thread creation failed: %s\n", strerror(ret));
- invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
+ (void)invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
secure_socket_destroy_handle(tcb->handle);
tcb_destroy(tcb);
return -EFAULT;
}
if (ret != 0) {
ErrPrint("Thread creation failed: %s\n", strerror(ret));
- invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
+ (void)invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
secure_socket_destroy_handle(tcb->handle);
tcb_destroy(tcb);
return -EFAULT;
continue;
}
- invoke_disconn_cb_list(handle, 0, 0, 0);
- terminate_thread(tcb);
- tcb_destroy(tcb);
+ if (invoke_disconn_cb_list(handle, 0, 0, 0) == 0) {
+ terminate_thread(tcb);
+ tcb_destroy(tcb);
+ }
return 0;
}
continue;
}
- invoke_disconn_cb_list(handle, 0, 0, 0);
- server_destroy(server);
+ if (invoke_disconn_cb_list(handle, 0, 0, 0) == 0) {
+ server_destroy(server);
+ }
return 0;
}
return -ENOENT;
}
- invoke_disconn_cb_list(handle, 0, 0, 0);
- terminate_thread(tcb);
- tcb_destroy(tcb);
+ if (invoke_disconn_cb_list(handle, 0, 0, 0) == 0) {
+ terminate_thread(tcb);
+ tcb_destroy(tcb);
+ }
return 0;
}