automatically restart sshd if the system kills it (or it crashes). but

don't restart it if it dies twice within 10 seconds.
only access sshd_pid (et al) from a few select spots now, with proper
synchronization.
sigsegv_dump
Greg Alexander 8 years ago
parent 2aeae24aed
commit 73d4406ee1

@ -25,7 +25,6 @@ conf_path_file(const char *fn)
static JNIEnv *env; static JNIEnv *env;
static jclass cl_string; static jclass cl_string;
static jclass cl_simplesshdservice; static jclass cl_simplesshdservice;
static jfieldID fid_sss_sshd_pid;
extern int dropbear_main(int argc, char **argv); extern int dropbear_main(int argc, char **argv);
@ -49,8 +48,6 @@ jni_init(JNIEnv *env_)
CLASS(string, "java/lang/String") CLASS(string, "java/lang/String")
CLASS(simplesshdservice, "org/galexander/sshd/SimpleSSHDService") CLASS(simplesshdservice, "org/galexander/sshd/SimpleSSHDService")
STFIELD(sss_sshd_pid, simplesshdservice, "sshd_pid", "I")
return 1; return 1;
} }
@ -115,7 +112,7 @@ from_java_string(jobject s)
return ret; return ret;
} }
JNIEXPORT void JNICALL JNIEXPORT jint JNICALL
Java_org_galexander_sshd_SimpleSSHDService_start_1sshd(JNIEnv *env_, Java_org_galexander_sshd_SimpleSSHDService_start_1sshd(JNIEnv *env_,
jclass cl, jclass cl,
jint port, jobject jpath, jobject jshell, jobject jhome, jobject jextra, jint port, jobject jpath, jobject jshell, jobject jhome, jobject jextra,
@ -167,23 +164,18 @@ Java_org_galexander_sshd_SimpleSSHDService_start_1sshd(JNIEnv *env_,
(sizeof argv / sizeof *argv) - argc); (sizeof argv / sizeof *argv) - argc);
fprintf(stderr, "starting dropbear\n"); fprintf(stderr, "starting dropbear\n");
retval = dropbear_main(argc, argv); retval = dropbear_main(argc, argv);
/* NB - probably not reachable */
fprintf(stderr, "dropbear finished (%d)\n", retval); fprintf(stderr, "dropbear finished (%d)\n", retval);
} else { exit(0);
(*env)->SetStaticIntField(env, cl_simplesshdservice,
fid_sss_sshd_pid, pid);
} }
return pid;
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_org_galexander_sshd_SimpleSSHDService_stop_1sshd(JNIEnv *env_, jclass cl) Java_org_galexander_sshd_SimpleSSHDService_kill(JNIEnv *env_, jclass cl,
jint pid)
{ {
pid_t pid;
if (!jni_init(env_)) {
return;
}
pid = (*env)->GetStaticIntField(env, cl_simplesshdservice, fid_sss_sshd_pid);
kill(pid, SIGKILL); kill(pid, SIGKILL);
(*env)->SetStaticIntField(env, cl_simplesshdservice, fid_sss_sshd_pid, 0);
} }
JNIEXPORT int JNICALL JNIEXPORT int JNICALL

@ -9,7 +9,13 @@ import java.io.File;
import java.io.FileReader; import java.io.FileReader;
public class SimpleSSHDService extends Service { public class SimpleSSHDService extends Service {
public static int sshd_pid = 0; /* if restarting twice within 10 seconds, give up */
private static final int MIN_DURATION = 10000;
private static final Object lock = new Object();
private static int sshd_pid = 0;
private static long sshd_when = 0;
private static long sshd_duration = 0;
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@ -17,11 +23,8 @@ public class SimpleSSHDService extends Service {
Prefs.init(this); Prefs.init(this);
read_pidfile(); read_pidfile();
if (is_started()) {
/* would prefer to restart the daemon process rather stop_sshd(); /* it would be stale anyways */
* than leave the stale one around.. */
stop_sshd();
}
} }
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
@ -48,9 +51,7 @@ public class SimpleSSHDService extends Service {
/* unfortunately, android doesn't reliably call this when, i.e., /* unfortunately, android doesn't reliably call this when, i.e.,
* the package is upgraded... so it's really pretty useless */ * the package is upgraded... so it's really pretty useless */
public void onDestroy() { public void onDestroy() {
if (is_started()) { stop_sshd();
stop_sshd();
}
stopSelf(); stopSelf();
super.onDestroy(); super.onDestroy();
} }
@ -59,23 +60,55 @@ public class SimpleSSHDService extends Service {
return (sshd_pid != 0); return (sshd_pid != 0);
} }
private void do_start() { private static void stop_sshd() {
if (is_started()) { int pid;
stop_sshd(); synchronized (lock) {
pid = sshd_pid;
sshd_pid = 0;
}
if (pid != 0) {
kill(pid);
} }
start_sshd(Prefs.get_port(), }
private static void maybe_restart(int pid) {
boolean do_restart = false;
long now = System.currentTimeMillis();
synchronized (lock) {
if (sshd_pid == pid) {
sshd_pid = 0;
do_restart =
((sshd_duration == 0) ||
(sshd_when == 0) ||
(sshd_duration >= MIN_DURATION) ||
((now-sshd_when) >= MIN_DURATION));
}
}
if (do_restart) {
do_start();
}
}
private static void do_start() {
stop_sshd();
final int pid = start_sshd(Prefs.get_port(),
Prefs.get_path(), Prefs.get_shell(), Prefs.get_path(), Prefs.get_shell(),
Prefs.get_home(), Prefs.get_extra(), Prefs.get_home(), Prefs.get_extra(),
(Prefs.get_rsyncbuffer() ? 1 : 0)); (Prefs.get_rsyncbuffer() ? 1 : 0));
if (sshd_pid != 0) { long now = System.currentTimeMillis();
final int pid = sshd_pid; if (pid != 0) {
synchronized (lock) {
stop_sshd();
sshd_pid = pid;
sshd_duration = ((sshd_when != 0)
? (now - sshd_when) : 0);
sshd_when = now;
}
(new Thread() { (new Thread() {
public void run() { public void run() {
waitpid(pid); waitpid(pid);
if (sshd_pid == pid) { maybe_restart(pid);
sshd_pid = 0;
}
SimpleSSHD.update_startstop(); SimpleSSHD.update_startstop();
} }
}).start(); }).start();
@ -86,23 +119,32 @@ public class SimpleSSHDService extends Service {
private static void read_pidfile() { private static void read_pidfile() {
try { try {
File f = new File(Prefs.get_path(), "dropbear.pid"); File f = new File(Prefs.get_path(), "dropbear.pid");
int pid = 0;
if (f.exists()) { if (f.exists()) {
BufferedReader r = new BufferedReader( BufferedReader r = new BufferedReader(
new FileReader(f)); new FileReader(f));
try { try {
sshd_pid = pid =
Integer.valueOf(r.readLine()); Integer.valueOf(r.readLine());
} finally { } finally {
r.close(); r.close();
} }
} }
if (pid != 0) {
synchronized (lock) {
stop_sshd();
sshd_pid = pid;
sshd_when = System.currentTimeMillis();
sshd_duration = 0;
}
}
} catch (Exception e) { /* *shrug* */ } } catch (Exception e) { /* *shrug* */ }
} }
private static native void start_sshd(int port, String path, private static native int start_sshd(int port, String path,
String shell, String home, String extra, String shell, String home, String extra,
int rsyncbuffer); int rsyncbuffer);
private static native void stop_sshd(); private static native void kill(int pid);
private static native int waitpid(int pid); private static native int waitpid(int pid);
static { static {
System.loadLibrary("simplesshd-jni"); System.loadLibrary("simplesshd-jni");

Loading…
Cancel
Save