made sc_sock_poll sc_sock_pipe and cond immune to double termination

This commit is contained in:
tezc 2021-04-14 23:16:36 +03:00
parent 8c8a3ede9f
commit e1ef96ad61
5 changed files with 87 additions and 16 deletions

View File

@ -299,6 +299,7 @@ void test1()
assert(sc_thread_term(&thread1) == 0);
assert(sc_thread_term(&thread2) == 0);
assert(sc_cond_term(&cond) == 0);
assert(sc_cond_term(&cond) == 0);
assert(sc_cond_init(&cond) == 0);
sc_thread_init(&thread1);
@ -308,6 +309,7 @@ void test1()
assert(sc_thread_term(&thread1) == 0);
assert(sc_thread_term(&thread2) == 0);
assert(sc_cond_term(&cond) == 0);
assert(sc_cond_term(&cond) == 0);
assert(sc_cond_init(&cond) == 0);
sc_thread_init(&thread1);
@ -317,6 +319,7 @@ void test1()
assert(sc_thread_term(&thread1) == 0);
assert(sc_thread_term(&thread2) == 0);
assert(sc_cond_term(&cond) == 0);
assert(sc_cond_term(&cond) == 0);
}
int main()

View File

@ -36,7 +36,7 @@
int sc_cond_init(struct sc_cond *c)
{
*c = (struct sc_cond){0};
*c = (struct sc_cond){.init = true};
InitializeCriticalSection(&c->mtx);
InitializeConditionVariable(&c->cond);
@ -46,7 +46,12 @@ int sc_cond_init(struct sc_cond *c)
int sc_cond_term(struct sc_cond *c)
{
if (!c.init) {
return 0;
}
DeleteCriticalSection(&c->mtx);
c.init = false;
return 0;
}
@ -117,6 +122,7 @@ int sc_cond_init(struct sc_cond *c)
}
pthread_mutexattr_destroy(&attr);
c->init = true;
return 0;
@ -135,6 +141,10 @@ int sc_cond_term(struct sc_cond *c)
errno = 0;
if (!c->init) {
return 0;
}
rc = pthread_mutex_destroy(&c->mtx);
if (rc != 0) {
errno = rc;
@ -145,6 +155,8 @@ int sc_cond_term(struct sc_cond *c)
errno = rc;
}
c->init = false;
return errno;
}

View File

@ -36,6 +36,7 @@
#endif
struct sc_cond {
bool init;
bool done;
void *data;

View File

@ -40,18 +40,18 @@
#endif
#if defined(_WIN32) || defined(_WIN64)
#include <Ws2tcpip.h>
#include <afunix.h>
#include <assert.h>
#include <Ws2tcpip.h>
#pragma warning(disable : 4996)
#define sc_close(n) closesocket(n)
#define sc_unlink(n) DeleteFileA(n)
#define SC_ERR SOCKET_ERROR
#define SC_INVALID INVALID_SOCKET
#define SC_EAGAIN WSAEWOULDBLOCK
#define sc_close(n) closesocket(n)
#define sc_unlink(n) DeleteFileA(n)
#define SC_ERR SOCKET_ERROR
#define SC_INVALID INVALID_SOCKET
#define SC_EAGAIN WSAEWOULDBLOCK
#define SC_EINPROGRESS WSAEINPROGRESS
#define SC_EINTR WSAEINTR
#define SC_EINTR WSAEINTR
typedef int socklen_t;
@ -120,13 +120,13 @@ int sc_sock_notify_systemd(const char *msg)
#include <sys/un.h>
#include <unistd.h>
#define sc_close(n) close(n)
#define sc_unlink(n) unlink(n)
#define SC_ERR (-1)
#define SC_INVALID (-1)
#define SC_EAGAIN EAGAIN
#define sc_close(n) close(n)
#define sc_unlink(n) unlink(n)
#define SC_ERR (-1)
#define SC_INVALID (-1)
#define SC_EAGAIN EAGAIN
#define SC_EINPROGRESS EINPROGRESS
#define SC_EINTR EINTR
#define SC_EINTR EINTR
int sc_sock_notify_systemd(const char *msg)
{
@ -880,6 +880,10 @@ int sc_sock_pipe_init(struct sc_sock_pipe *p, int type)
int val = 1;
BOOL nodelay = 1;
*p = (struct sc_sock_pipe){
.fds = {SC_INVALID, SC_INVALID},
};
p->fdt.type = type;
p->fdt.op = SC_SOCK_NONE;
p->fdt.index = -1;
@ -952,6 +956,10 @@ int sc_sock_pipe_term(struct sc_sock_pipe *p)
{
int rc = 0, rv;
if (p->fds[0] == SC_INVALID) {
return 0;
}
rv = closesocket(p->fds[0]);
if (rv != 0) {
rc = -1;
@ -1001,6 +1009,10 @@ int sc_sock_pipe_init(struct sc_sock_pipe *p, int type)
{
int rc;
*p = (struct sc_sock_pipe){
.fds = {SC_INVALID, SC_INVALID},
};
rc = pipe(p->fds);
if (rc != 0) {
sc_sock_pipe_set_err(p, "pipe() : %s ", strerror(errno));
@ -1018,6 +1030,10 @@ int sc_sock_pipe_term(struct sc_sock_pipe *p)
{
int rc = 0, rv;
if (p->fds[0] == SC_INVALID) {
return 0;
}
rv = close(p->fds[0]);
if (rv != 0) {
rc = -1;
@ -1030,6 +1046,9 @@ int sc_sock_pipe_term(struct sc_sock_pipe *p)
sc_sock_pipe_set_err(p, "pipe close() : %s ", strerror(errno));
}
p->fds[0] = SC_INVALID;
p->fds[1] = SC_INVALID;
return rc;
}
@ -1114,8 +1133,18 @@ error:
int sc_sock_poll_term(struct sc_sock_poll *p)
{
int rc;
if (!p->events) {
return 0;
}
sc_sock_free(p->events);
return close(p->fds);
rc = close(p->fds);
*p = (struct sc_sock_poll){0};
return rc;
}
static int sc_sock_poll_expand(struct sc_sock_poll *p)
@ -1328,8 +1357,18 @@ err:
int sc_sock_poll_term(struct sc_sock_poll *p)
{
int rc;
if (!p->events) {
return 0;
}
sc_sock_free(p->events);
return close(p->fds);
rc = close(p->fds);
*p = (struct sc_sock_poll){0};
return rc;
}
int sc_sock_poll_add(struct sc_sock_poll *p, struct sc_sock_fd *fdt,
@ -1468,14 +1507,24 @@ int sc_sock_poll_init(struct sc_sock_poll *p)
return 0;
err:
sc_sock_free(p->events);
p->events = NULL;
p->data = NULL;
sc_sock_poll_set_err(p, "Out of memory.");
return -1;
}
int sc_sock_poll_term(struct sc_sock_poll *p)
{
if (p->events == NULL) {
return 0;
}
sc_sock_free(p->events);
sc_sock_free(p->data);
p->events = NULL;
p->data = NULL;
return 0;
}

View File

@ -411,9 +411,11 @@ void test_poll_mass(void)
assert(sc_sock_poll_del(&poll, &pipe[i].fdt, SC_SOCK_READ,
NULL) == 0);
assert(sc_sock_pipe_term(&pipe[i]) == 0);
assert(sc_sock_pipe_term(&pipe[i]) == 0);
}
assert(poll.count == 0);
assert(sc_sock_poll_term(&poll) == 0);
assert(sc_sock_poll_term(&poll) == 0);
assert(sc_sock_poll_init(&poll) == 0);
for (int i = 0; i < 100; i++) {
@ -428,6 +430,7 @@ void test_poll_mass(void)
assert(sc_sock_poll_del(&poll, &pipe[i].fdt, SC_SOCK_WRITE,
NULL) == 0);
assert(sc_sock_pipe_term(&pipe[i]) == 0);
assert(sc_sock_pipe_term(&pipe[i]) == 0);
}
assert(poll.count == 0);
assert(sc_sock_poll_term(&poll) == 0);
@ -445,9 +448,11 @@ void test_poll_mass(void)
assert(sc_sock_poll_del(&poll, &pipe[i].fdt, SC_SOCK_READ,
NULL) == 0);
assert(sc_sock_pipe_term(&pipe[i]) == 0);
assert(sc_sock_pipe_term(&pipe[i]) == 0);
}
assert(poll.count == 0);
assert(sc_sock_poll_term(&poll) == 0);
assert(sc_sock_poll_term(&poll) == 0);
assert(sc_sock_poll_init(&poll) == 0);
for (int i = 0; i < 100; i++) {
@ -842,6 +847,7 @@ void poll_fail_test()
fail_epoll_wait = 1;
assert(sc_sock_poll_wait(&poll, 10) == 0);
assert(sc_sock_poll_term(&poll) == 0);
assert(sc_sock_poll_term(&poll) == 0);
assert(sc_sock_poll_init(&poll) == 0);
sc_sock_init(&sock, 0, true, AF_INET);