|
|
@@ -3510,6 +3510,25 @@ static void send_result(struct io_data *io_data, SOCKETTYPE c, bool isjson)
|
|
|
(long)bytes_len(&io_data->data));
|
|
|
}
|
|
|
|
|
|
+static
|
|
|
+void _tidyup_socket(SOCKETTYPE * const sockp)
|
|
|
+{
|
|
|
+ if (*sockp != INVSOCK) {
|
|
|
+ shutdown(*sockp, SHUT_RDWR);
|
|
|
+ CLOSESOCKET(*sockp);
|
|
|
+ *sockp = INVSOCK;
|
|
|
+ free(sockp);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static
|
|
|
+void tidyup_socket(void * const arg)
|
|
|
+{
|
|
|
+ mutex_lock(&quit_restart_lock);
|
|
|
+ _tidyup_socket(arg);
|
|
|
+ mutex_unlock(&quit_restart_lock);
|
|
|
+}
|
|
|
+
|
|
|
static void tidyup(__maybe_unused void *arg)
|
|
|
{
|
|
|
mutex_lock(&quit_restart_lock);
|
|
|
@@ -3518,12 +3537,7 @@ static void tidyup(__maybe_unused void *arg)
|
|
|
|
|
|
bye = true;
|
|
|
|
|
|
- if (*apisock != INVSOCK) {
|
|
|
- shutdown(*apisock, SHUT_RDWR);
|
|
|
- CLOSESOCKET(*apisock);
|
|
|
- *apisock = INVSOCK;
|
|
|
- free(apisock);
|
|
|
- }
|
|
|
+ _tidyup_socket(apisock);
|
|
|
|
|
|
if (ipaccess != NULL) {
|
|
|
free(ipaccess);
|
|
|
@@ -3839,7 +3853,7 @@ static void mcast()
|
|
|
struct sockaddr_in came_from;
|
|
|
struct timeval bindstart;
|
|
|
const char *binderror;
|
|
|
- SOCKETTYPE mcast_sock;
|
|
|
+ SOCKETTYPE *mcastsock;
|
|
|
SOCKETTYPE reply_sock;
|
|
|
socklen_t came_from_siz;
|
|
|
char *connectaddr;
|
|
|
@@ -3862,10 +3876,14 @@ static void mcast()
|
|
|
quit(1, "Invalid Multicast Address");
|
|
|
grp.imr_interface.s_addr = INADDR_ANY;
|
|
|
|
|
|
- mcast_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
+ mcastsock = malloc(sizeof(*mcastsock));
|
|
|
+ *mcastsock = INVSOCK;
|
|
|
+ pthread_cleanup_push(tidyup_socket, mcastsock);
|
|
|
+
|
|
|
+ *mcastsock = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
|
|
int optval = 1;
|
|
|
- if (SOCKETFAIL(setsockopt(mcast_sock, SOL_SOCKET, SO_REUSEADDR, (void *)(&optval), sizeof(optval)))) {
|
|
|
+ if (SOCKETFAIL(setsockopt(*mcastsock, SOL_SOCKET, SO_REUSEADDR, (void *)(&optval), sizeof(optval)))) {
|
|
|
applog(LOG_ERR, "API mcast setsockopt SO_REUSEADDR failed (%s)%s", SOCKERRMSG, MUNAVAILABLE);
|
|
|
goto die;
|
|
|
}
|
|
|
@@ -3879,7 +3897,7 @@ static void mcast()
|
|
|
bound = 0;
|
|
|
timer_set_now(&bindstart);
|
|
|
while (bound == 0) {
|
|
|
- if (SOCKETFAIL(bind(mcast_sock, (struct sockaddr *)(&listen), sizeof(listen)))) {
|
|
|
+ if (SOCKETFAIL(bind(*mcastsock, (struct sockaddr *)(&listen), sizeof(listen)))) {
|
|
|
binderror = SOCKERRMSG;
|
|
|
if (timer_elapsed(&bindstart, NULL) > 61)
|
|
|
break;
|
|
|
@@ -3894,7 +3912,7 @@ static void mcast()
|
|
|
goto die;
|
|
|
}
|
|
|
|
|
|
- if (SOCKETFAIL(setsockopt(mcast_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)(&grp), sizeof(grp)))) {
|
|
|
+ if (SOCKETFAIL(setsockopt(*mcastsock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)(&grp), sizeof(grp)))) {
|
|
|
applog(LOG_ERR, "API mcast join failed (%s)%s", SOCKERRMSG, MUNAVAILABLE);
|
|
|
goto die;
|
|
|
}
|
|
|
@@ -3911,10 +3929,10 @@ static void mcast()
|
|
|
|
|
|
count++;
|
|
|
came_from_siz = sizeof(came_from);
|
|
|
- if (SOCKETFAIL(rep = recvfrom(mcast_sock, buf, sizeof(buf) - 1,
|
|
|
+ if (SOCKETFAIL(rep = recvfrom(*mcastsock, buf, sizeof(buf) - 1,
|
|
|
0, (struct sockaddr *)(&came_from), &came_from_siz))) {
|
|
|
applog(LOG_DEBUG, "API mcast failed count=%d (%s) (%d)",
|
|
|
- count, SOCKERRMSG, (int)mcast_sock);
|
|
|
+ count, SOCKERRMSG, (int)*mcastsock);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
@@ -3961,6 +3979,7 @@ static void mcast()
|
|
|
replybuf, (int)rep, (int)reply_sock);
|
|
|
}
|
|
|
|
|
|
+ shutdown(reply_sock, SHUT_RDWR);
|
|
|
CLOSESOCKET(reply_sock);
|
|
|
}
|
|
|
} else
|
|
|
@@ -3968,8 +3987,8 @@ static void mcast()
|
|
|
}
|
|
|
|
|
|
die:
|
|
|
-
|
|
|
- CLOSESOCKET(mcast_sock);
|
|
|
+ ; // statement in case pthread_cleanup_pop doesn't start with one
|
|
|
+ pthread_cleanup_pop(true);
|
|
|
}
|
|
|
|
|
|
static void *mcast_thread(void *userdata)
|
|
|
@@ -4048,14 +4067,14 @@ void api(int api_thr_id)
|
|
|
|
|
|
if (ips == 0) {
|
|
|
applog(LOG_WARNING, "API not running (no valid IPs specified)%s", UNAVAILABLE);
|
|
|
- return;
|
|
|
+ pthread_exit(NULL);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
*apisock = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
if (*apisock == INVSOCK) {
|
|
|
applog(LOG_ERR, "API1 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
|
|
|
- return;
|
|
|
+ pthread_exit(NULL);
|
|
|
}
|
|
|
|
|
|
memset(&serv, 0, sizeof(serv));
|
|
|
@@ -4066,7 +4085,7 @@ void api(int api_thr_id)
|
|
|
serv.sin_addr.s_addr = inet_addr(localaddr);
|
|
|
if (serv.sin_addr.s_addr == (in_addr_t)INVINETADDR) {
|
|
|
applog(LOG_ERR, "API2 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
|
|
|
- return;
|
|
|
+ pthread_exit(NULL);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -4104,13 +4123,12 @@ void api(int api_thr_id)
|
|
|
|
|
|
if (bound == 0) {
|
|
|
applog(LOG_ERR, "API bind to port %d failed (%s)%s", port, binderror, UNAVAILABLE);
|
|
|
- return;
|
|
|
+ pthread_exit(NULL);
|
|
|
}
|
|
|
|
|
|
if (SOCKETFAIL(listen(*apisock, QUEUE))) {
|
|
|
applog(LOG_ERR, "API3 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
|
|
|
- CLOSESOCKET(*apisock);
|
|
|
- return;
|
|
|
+ pthread_exit(NULL);
|
|
|
}
|
|
|
|
|
|
if (opt_api_allow)
|
|
|
@@ -4297,6 +4315,7 @@ inochi:
|
|
|
send_result(io_data, c, isjson);
|
|
|
}
|
|
|
}
|
|
|
+ shutdown(c, SHUT_RDWR);
|
|
|
CLOSESOCKET(c);
|
|
|
}
|
|
|
die:
|