|
|
@@ -44,6 +44,7 @@
|
|
|
#include <openssl/ssl.h>
|
|
|
#include <openssl/x509.h>
|
|
|
#include <pthread.h>
|
|
|
+#include <signal.h>
|
|
|
#include <stdio.h>
|
|
|
#include <stdlib.h>
|
|
|
#include <string.h>
|
|
|
@@ -52,6 +53,7 @@
|
|
|
#include <sys/ioctl.h>
|
|
|
#include <sys/socket.h>
|
|
|
#include <sys/types.h>
|
|
|
+#include <sys/wait.h>
|
|
|
|
|
|
#define DNS_MAX_EVENTS 256
|
|
|
#define IPV6_READY_CHECK_TIME 180
|
|
|
@@ -322,6 +324,9 @@ struct dns_server {
|
|
|
int event_fd;
|
|
|
struct list_head conn_list;
|
|
|
|
|
|
+ pid_t cache_save_pid;
|
|
|
+ time_t cache_save_time;
|
|
|
+
|
|
|
/* dns request list */
|
|
|
pthread_mutex_t request_list_lock;
|
|
|
struct list_head request_list;
|
|
|
@@ -350,6 +355,7 @@ static int _dns_server_reply_all_pending_list(struct dns_request *request, struc
|
|
|
static void *_dns_server_get_dns_rule(struct dns_request *request, enum domain_rule rule);
|
|
|
static const char *_dns_server_get_request_groupname(struct dns_request *request);
|
|
|
static int _dns_server_tcp_socket_send(struct dns_server_conn_tcp_client *tcp_client, void *data, int data_len);
|
|
|
+static int _dns_server_cache_save(int check_lock);
|
|
|
|
|
|
int dns_is_ipv6_ready(void)
|
|
|
{
|
|
|
@@ -6252,6 +6258,66 @@ static void _dns_server_check_need_exit(void)
|
|
|
#define _dns_server_check_need_exit()
|
|
|
#endif
|
|
|
|
|
|
+static void _dns_server_save_cache_to_file(void)
|
|
|
+{
|
|
|
+ time_t now;
|
|
|
+ int check_time = dns_conf_cache_checkpoint_time;
|
|
|
+
|
|
|
+ if (dns_conf_cache_persist == 0 || dns_conf_cachesize <= 0 || dns_conf_cache_checkpoint_time <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ time(&now);
|
|
|
+ if (server.cache_save_pid > 0) {
|
|
|
+ int ret = waitpid(server.cache_save_pid, NULL, WNOHANG);
|
|
|
+ if (ret == server.cache_save_pid) {
|
|
|
+ server.cache_save_pid = 0;
|
|
|
+ } else if (ret < 0) {
|
|
|
+ tlog(TLOG_ERROR, "waitpid failed, errno %d, error info '%s'", errno, strerror(errno));
|
|
|
+ server.cache_save_pid = 0;
|
|
|
+ } else {
|
|
|
+ if (now - 30 > server.cache_save_time) {
|
|
|
+ kill(server.cache_save_pid, SIGKILL);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (check_time < 120) {
|
|
|
+ check_time = 120;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (now - check_time < server.cache_save_time) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* server is busy, skip*/
|
|
|
+ pthread_mutex_lock(&server.request_list_lock);
|
|
|
+ if (list_empty(&server.request_list) != 0) {
|
|
|
+ pthread_mutex_unlock(&server.request_list_lock);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ pthread_mutex_unlock(&server.request_list_lock);
|
|
|
+
|
|
|
+ server.cache_save_time = now;
|
|
|
+
|
|
|
+ int pid = fork();
|
|
|
+ if (pid == 0) {
|
|
|
+ /* child process */
|
|
|
+ for (int i = 3; i < 1024; i++) {
|
|
|
+ close(i);
|
|
|
+ }
|
|
|
+
|
|
|
+ _dns_server_cache_save(1);
|
|
|
+ _exit(0);
|
|
|
+ } else if (pid < 0) {
|
|
|
+ tlog(TLOG_DEBUG, "fork failed, errno %d, error info '%s'", errno, strerror(errno));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ server.cache_save_pid = pid;
|
|
|
+}
|
|
|
+
|
|
|
static void _dns_server_period_run_second(void)
|
|
|
{
|
|
|
static unsigned int sec = 0;
|
|
|
@@ -6305,6 +6371,8 @@ static void _dns_server_period_run_second(void)
|
|
|
tlog(TLOG_INFO, "Update host file data");
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ _dns_server_save_cache_to_file();
|
|
|
}
|
|
|
|
|
|
static void _dns_server_period_run(unsigned int msec)
|
|
|
@@ -6902,7 +6970,7 @@ static int _dns_server_cache_init(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int _dns_server_cache_save(void)
|
|
|
+static int _dns_server_cache_save(int check_lock)
|
|
|
{
|
|
|
char *dns_cache_file = SMARTDNS_CACHE_FILE;
|
|
|
if (dns_conf_cache_file[0] != 0) {
|
|
|
@@ -6916,7 +6984,7 @@ static int _dns_server_cache_save(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- if (dns_cache_save(dns_cache_file) != 0) {
|
|
|
+ if (dns_cache_save(dns_cache_file, check_lock) != 0) {
|
|
|
tlog(TLOG_WARN, "save cache failed.");
|
|
|
return -1;
|
|
|
}
|
|
|
@@ -6974,6 +7042,7 @@ int dns_server_init(void)
|
|
|
memset(&server, 0, sizeof(server));
|
|
|
pthread_attr_init(&attr);
|
|
|
INIT_LIST_HEAD(&server.conn_list);
|
|
|
+ time(&server.cache_save_time);
|
|
|
|
|
|
epollfd = epoll_create1(EPOLL_CLOEXEC);
|
|
|
if (epollfd < 0) {
|
|
|
@@ -7034,8 +7103,14 @@ void dns_server_exit(void)
|
|
|
close(server.event_fd);
|
|
|
server.event_fd = -1;
|
|
|
}
|
|
|
+
|
|
|
+ if (server.cache_save_pid > 0) {
|
|
|
+ kill(server.cache_save_pid, SIGKILL);
|
|
|
+ server.cache_save_pid = 0;
|
|
|
+ }
|
|
|
+
|
|
|
_dns_server_close_socket();
|
|
|
- _dns_server_cache_save();
|
|
|
+ _dns_server_cache_save(0);
|
|
|
_dns_server_request_remove_all();
|
|
|
pthread_mutex_destroy(&server.request_list_lock);
|
|
|
dns_cache_destroy();
|