clatd: rework sigterm & error handling
Separate 'running' flag out into 'running' and 'sigterm',
and make SIGTERM handler the only thing that sets 'sigterm'.
running is cleared via catastrophic errors, ie. EOF and ENETDOWN
Test: TreeHugger
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I8254c3f4643d60feff1cb32aaa9784dca18e138c
diff --git a/clatd/clatd.c b/clatd/clatd.c
index 9ac1663..9b1d987 100644
--- a/clatd/clatd.c
+++ b/clatd/clatd.c
@@ -49,7 +49,8 @@
struct clat_config Global_Clatd_Config;
-volatile sig_atomic_t running = 1;
+volatile sig_atomic_t sigterm = 0;
+bool running = true;
// reads IPv6 packet from AF_PACKET socket, translates to IPv4, writes to tun
void process_packet_6_to_4(struct tun_data *tunnel) {
@@ -78,10 +79,11 @@
if (errno != EAGAIN) {
logmsg(ANDROID_LOG_WARN, "%s: read error: %s", __func__, strerror(errno));
}
+ if (errno == ENETDOWN) running = false;
return;
} else if (readlen == 0) {
logmsg(ANDROID_LOG_WARN, "%s: packet socket removed?", __func__);
- running = 0;
+ running = false;
return;
} else if (readlen >= sizeof(buf)) {
logmsg(ANDROID_LOG_WARN, "%s: read truncation - ignoring pkt", __func__);
@@ -161,10 +163,11 @@
if (errno != EAGAIN) {
logmsg(ANDROID_LOG_WARN, "%s: read error: %s", __func__, strerror(errno));
}
+ if (errno == ENETDOWN) running = false; // not sure if this can happen
return;
} else if (readlen == 0) {
logmsg(ANDROID_LOG_WARN, "%s: tun interface removed", __func__);
- running = 0;
+ running = false;
return;
} else if (readlen >= sizeof(buf)) {
logmsg(ANDROID_LOG_WARN, "%s: read truncation - ignoring pkt", __func__);
@@ -278,7 +281,7 @@
{ tunnel->fd4, POLLIN, 0 },
};
- while (running) {
+ while (running && !sigterm) {
if (poll(wait_fd, ARRAY_SIZE(wait_fd), -1) == -1) {
if (errno != EINTR) {
logmsg(ANDROID_LOG_WARN, "event_loop/poll returned an error: %s", strerror(errno));
diff --git a/clatd/clatd.h b/clatd/clatd.h
index 5b2b2e6..daa5ebc 100644
--- a/clatd/clatd.h
+++ b/clatd/clatd.h
@@ -52,7 +52,7 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-extern volatile sig_atomic_t running;
+extern volatile sig_atomic_t sigterm;
void send_dad(int fd, const struct in6_addr* tgt);
diff --git a/clatd/main.c b/clatd/main.c
index 11067de..1d2b227 100644
--- a/clatd/main.c
+++ b/clatd/main.c
@@ -34,10 +34,10 @@
#define DEVICEPREFIX "v4-"
-/* function: stop_loop
+/* function: handle_sigterm
* signal handler: stop the event loop
*/
-static void stop_loop(__attribute__((unused)) int unused) { running = 0; };
+static void handle_sigterm(__attribute__((unused)) int unused) { sigterm = 1; };
/* function: print_help
* in case the user is running this on the command line
@@ -183,7 +183,7 @@
}
// Loop until someone sends us a signal or brings down the tun interface.
- if (signal(SIGTERM, stop_loop) == SIG_ERR) {
+ if (signal(SIGTERM, handle_sigterm) == SIG_ERR) {
logmsg(ANDROID_LOG_FATAL, "sigterm handler failed: %s", strerror(errno));
exit(1);
}
@@ -203,16 +203,17 @@
logmsg(ANDROID_LOG_INFO, "Shutting down clat on %s", uplink_interface);
- if (running) {
+ if (sigterm) {
+ logmsg(ANDROID_LOG_INFO, "Clatd on %s already received SIGTERM", uplink_interface);
+ } else {
+ // this implies running == false, ie. we received EOF or ENETDOWN error.
logmsg(ANDROID_LOG_INFO, "Clatd on %s waiting for SIGTERM", uplink_interface);
// let's give higher level java code 15 seconds to kill us,
// but eventually terminate anyway, in case system server forgets about us...
- // sleep() should be interrupted by SIGTERM, the handler should clear running
+ // sleep() should be interrupted by SIGTERM, the handler should set 'sigterm'
sleep(15);
logmsg(ANDROID_LOG_INFO, "Clatd on %s %s SIGTERM", uplink_interface,
- running ? "timed out waiting for" : "received");
- } else {
- logmsg(ANDROID_LOG_INFO, "Clatd on %s already received SIGTERM", uplink_interface);
+ sigterm ? "received" : "timed out waiting for");
}
return 0;
}