pthread_t thid; /*!< Thread Id */
int fd; /*!< Connection handle */
enum tcb_type type;
+ int ctrl_pipe[PIPE_MAX];
};
/*!
int recv_offset;
int pid;
int ret;
+ int fd;
char evt_ch = EVT_CH;
enum {
RECV_INIT,
while (ret == 0) {
FD_ZERO(&set);
FD_SET(tcb->fd, &set);
- ret = select(tcb->fd + 1, &set, NULL, NULL, NULL);
+ FD_SET(tcb->ctrl_pipe[PIPE_READ], &set);
+ fd = tcb->fd > tcb->ctrl_pipe[PIPE_READ] ? tcb->fd : tcb->ctrl_pipe[PIPE_READ];
+ ret = select(fd + 1, &set, NULL, NULL, NULL);
if (ret < 0) {
ret = -errno;
if (errno == EINTR) {
break;
}
+ if (FD_ISSET(tcb->ctrl_pipe[PIPE_READ], &set)) {
+ DbgPrint("Thread is canceled\n");
+ ret = -ECANCELED;
+ free(ptr);
+ ptr = NULL;
+ break;
+ }
+
if (!FD_ISSET(tcb->fd, &set)) {
ErrPrint("Unexpected handler is toggled\n");
ret = -EINVAL;
return NULL;
}
+ if (pipe2(tcb->ctrl_pipe, O_NONBLOCK | O_CLOEXEC) < 0) {
+ ErrPrint("pipe2: %s\n", strerror(errno));
+ free(tcb);
+ return NULL;
+ }
+
tcb->fd = fd;
tcb->svc_ctx = svc_ctx;
tcb->type = TCB_CLIENT_TYPE_APP;
status = pthread_create(&tcb->thid, NULL, client_packet_pump_main, tcb);
if (status != 0) {
ErrPrint("Unable to create a new thread: %s\n", strerror(status));
+ CLOSE_PIPE(tcb->ctrl_pipe);
free(tcb);
return NULL;
}
struct tcb *tcb;
void *ret;
int status;
+ char ch = EVT_END_CH;
/*!
* We don't need to make critical section on here.
/*!
* ASSERT(tcb->fd >= 0);
*/
- secure_socket_destroy_handle(tcb->fd);
+ if (write(tcb->ctrl_pipe[PIPE_WRITE], &ch, sizeof(ch)) != sizeof(ch))
+ ErrPrint("write: %s\n", strerror(errno));
status = pthread_join(tcb->thid, &ret);
if (status != 0)
else
DbgPrint("Thread returns: %d\n", (int)ret);
+ secure_socket_destroy_handle(tcb->fd);
+
+ CLOSE_PIPE(tcb->ctrl_pipe);
free(tcb);
}
}
{
void *ret;
int status;
+ char ch = EVT_END_CH;
svc_ctx->tcb_list = eina_list_remove(svc_ctx->tcb_list, tcb);
/*!
* ASSERT(tcb->fd >= 0);
* Close the connection, and then collecting the return value of thread
*/
- secure_socket_destroy_handle(tcb->fd);
+ if (write(tcb->ctrl_pipe[PIPE_WRITE], &ch, sizeof(ch)) != sizeof(ch))
+ ErrPrint("write: %s\n", strerror(errno));
status = pthread_join(tcb->thid, &ret);
if (status != 0)
else
DbgPrint("Thread returns: %d\n", (int)ret);
+ secure_socket_destroy_handle(tcb->fd);
+
+ CLOSE_PIPE(tcb->ctrl_pipe);
free(tcb);
}
{
struct service_context *svc_ctx = data;
fd_set set;
+ fd_set except_set;
int ret;
int client_fd;
struct tcb *tcb;
DbgPrint("Server thread is activated\n");
while (1) {
fd = update_fdset(svc_ctx, &set);
+ memcpy(&except_set, &set, sizeof(set));
- ret = select(fd, &set, NULL, NULL, NULL);
+ ret = select(fd, &set, NULL, &except_set, NULL);
if (ret < 0) {
ret = -errno;
if (errno == EINTR) {
break;
}
+ if (!tcb) {
+ ErrPrint("Terminate service thread\n");
+ ret = -ECANCELED;
+ break;
+ }
+
/*!
* \note
* Invoke the service thread main, to notify the termination of a TCB
svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info);
CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
- /*!
- * \CRITICAL
- * What happens if the client thread is terminated, so the packet_info->tcb is deleted
- * while processing svc_ctx->service_thread_main?
- */
- ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data);
- if (ret < 0)
- ErrPrint("Service thread returns: %d\n", ret);
-
- packet_destroy(packet_info->packet);
- free(packet_info);
+ if (packet_info) {
+ /*!
+ * \CRITICAL
+ * What happens if the client thread is terminated, so the packet_info->tcb is deleted
+ * while processing svc_ctx->service_thread_main?
+ */
+ ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data);
+ if (ret < 0)
+ ErrPrint("Service thread returns: %d\n", ret);
+
+ packet_destroy(packet_info->packet);
+ free(packet_info);
+ }
}
processing_timer_event(svc_ctx, &set);
return NULL;
}
+ /*!
+ * \note
+ * To give a chance to run for server thread.
+ */
+ DbgPrint("Yield\n");
+ pthread_yield();
+
return svc_ctx;
}
*/
HAPI int service_common_destroy(struct service_context *svc_ctx)
{
- int status;
+ int status = 0;
void *ret;
if (!svc_ctx)
* \note
* Terminate server thread
*/
- secure_socket_destroy_handle(svc_ctx->fd);
+ if (write(svc_ctx->tcb_pipe[PIPE_WRITE], &status, sizeof(status)) != sizeof(status))
+ ErrPrint("Failed to write: %s\n", strerror(errno));
status = pthread_join(svc_ctx->server_thid, &ret);
if (status != 0)
else
DbgPrint("Thread returns: %d\n", (int)ret);
+ secure_socket_destroy_handle(svc_ctx->fd);
+
status = pthread_mutex_destroy(&svc_ctx->packet_list_lock);
if (status != 0)
ErrPrint("Unable to destroy a mutex: %s\n", strerror(status));
if (timerfd_settime(item->info.timer.fd, 0, &spec, NULL) < 0) {
ErrPrint("Error: %s\n", strerror(errno));
- close(item->info.timer.fd);
+ if (close(item->info.timer.fd) < 0)
+ ErrPrint("close: %s\n", strerror(errno));
free(item);
return NULL;
}
svc_ctx->event_list = eina_list_remove(svc_ctx->event_list, item);
- close(item->info.timer.fd);
+ if (close(item->info.timer.fd) < 0)
+ ErrPrint("close: %s\n", strerror(errno));
free(item);
return 0;
}
+HAPI int service_common_fd(struct service_context *ctx)
+{
+ return ctx->fd;
+}
+
/* End of a file */