diff --git a/btpd/btpd.c b/btpd/btpd.c
index 6d48d55..109c7b6 100644
--- a/btpd/btpd.c
+++ b/btpd/btpd.c
@@ -5,9 +5,9 @@
 
 static uint8_t m_peer_id[20];
 static struct timeout m_heartbeat;
-static struct timeout m_grace_timer;
 static int m_signal;
 static int m_shutdown;
+static int m_ghost;
 
 long btpd_seconds;
 
@@ -18,29 +18,35 @@ btpd_exit(int code)
     exit(code);
 }
 
+extern int pidfd;
+void ipc_shutdown(void);
+void net_shutdown(void);
+
 static void
-grace_cb(int fd, short type, void *arg)
+death_procedure(void)
 {
-    struct torrent *tp;
-    BTPDQ_FOREACH(tp, torrent_get_all(), entry)
-        torrent_stop(tp, 0);
+    assert(m_shutdown);
+    if (torrent_count() == 0)
+        btpd_exit(0);
+    if (!m_ghost && torrent_count() == torrent_ghosts()) {
+        btpd_log(BTPD_L_BTPD, "Entering pre exit mode. Bye!\n");
+        fclose(stderr);
+        fclose(stdout);
+        net_shutdown();
+        ipc_shutdown();
+        close(pidfd);
+        m_ghost = 1;
+    }
 }
 
 void
-btpd_shutdown(int grace_seconds)
+btpd_shutdown(void)
 {
-    if (torrent_count() == 0)
-        btpd_exit(0);
-    else {
-        struct torrent *tp;
-        m_shutdown = 1;
-        BTPDQ_FOREACH(tp, torrent_get_all(), entry)
-            if (tp->state != T_STOPPING)
-                torrent_stop(tp, 0);
-        if (grace_seconds >= 0)
-            btpd_timer_add(&m_grace_timer,
-                (& (struct timespec){ grace_seconds, 0 }));
-    }
+    m_shutdown = 1;
+    struct torrent *tp, *next;
+    BTPDQ_FOREACH_MUTABLE(tp, torrent_get_all(), entry, next)
+        torrent_stop(tp, 0);
+    death_procedure();
 }
 
 int btpd_is_stopping(void)
@@ -69,11 +75,12 @@ heartbeat_cb(int fd, short type, void *arg)
     torrent_on_tick_all();
     if (m_signal) {
         btpd_log(BTPD_L_BTPD, "Got signal %d.\n", m_signal);
-        btpd_shutdown(30);
         m_signal = 0;
+        if (!m_shutdown)
+            btpd_shutdown();
     }
-    if (m_shutdown && torrent_count() == 0)
-        btpd_exit(0);
+    if (m_shutdown)
+        death_procedure();
 }
 
 void tr_init(void);
@@ -123,7 +130,6 @@ btpd_init(void)
     tr_init();
     tlib_init();
 
-    timer_init(&m_grace_timer, grace_cb, NULL);
     timer_init(&m_heartbeat, heartbeat_cb, NULL);
     btpd_timer_add(&m_heartbeat, (& (struct timespec) { 1, 0 }));
 }
diff --git a/btpd/btpd.h b/btpd/btpd.h
index 4312a03..f28591d 100644
--- a/btpd/btpd.h
+++ b/btpd/btpd.h
@@ -82,7 +82,7 @@ void btpd_ev_disable(struct fdev *ev, uint16_t flags);
 void btpd_timer_add(struct timeout *to, struct timespec *ts);
 void btpd_timer_del(struct timeout *to);
 
-void btpd_shutdown(int grace_seconds);
+void btpd_shutdown(void);
 int btpd_is_stopping(void);
 
 const uint8_t *btpd_get_peer_id(void);
diff --git a/btpd/cli_if.c b/btpd/cli_if.c
index e129b88..61858b9 100644
--- a/btpd/cli_if.c
+++ b/btpd/cli_if.c
@@ -8,6 +8,7 @@ struct cli {
     struct fdev read;
 };
 
+static int m_listen_sd;
 static struct fdev m_cli_incoming;
 
 static int
@@ -135,6 +136,8 @@ write_ans(struct iobuf *iob, struct tlib *tl, enum ipc_tval val)
             case T_LEECH:
                 ts = IPC_TSTATE_LEECH;
                 break;
+            case T_GHOST:
+                break;
             }
         }
         iobuf_print(iob, "i%de", ts);
@@ -185,9 +188,10 @@ cmd_tget(struct cli *cli, int argc, const char *args)
         struct tlib *tlv[tlib_count()];
         tlib_put_all(tlv);
         for (int i = 0; i < sizeof(tlv) / sizeof(tlv[0]); i++) {
-            if ((from == IPC_TWC_ALL ||
-                    (tlv[i]->tp == NULL && from == IPC_TWC_INACTIVE) ||
-                    (tlv[i]->tp != NULL && from == IPC_TWC_ACTIVE))) {
+            if (!torrent_haunting(tlv[i]) && (
+                    from == IPC_TWC_ALL ||
+                    (!torrent_active(tlv[i]) && from == IPC_TWC_INACTIVE) ||
+                    (torrent_active(tlv[i]) && from == IPC_TWC_ACTIVE))) {
                 iobuf_swrite(&iob, "l");
                 for (int k = 0; k < nkeys; k++)
                     write_ans(&iob, tlv[i], opts[k]);
@@ -206,7 +210,7 @@ cmd_tget(struct cli *cli, int argc, const char *args)
                 free(opts);
                 return IPC_COMMERR;
             }
-            if (tl != NULL) {
+            if (tl != NULL && !torrent_haunting(tl)) {
                 iobuf_swrite(&iob, "l");
                 for (int i = 0; i < nkeys; i++)
                     write_ans(&iob, tl, opts[i]);
@@ -248,10 +252,15 @@ cmd_add(struct cli *cli, int argc, const char *args)
     content[csize] = '\0';
 
     tl = tlib_by_hash(mi_info_hash(mi, hash));
-    if (tl != NULL)
+    if (tl != NULL && !torrent_haunting(tl))
         return write_code_buffer(cli, IPC_ETENTEXIST);
-    tl = tlib_add(hash, mi, mi_size, content,
-        benc_dget_str(args, "name", NULL));
+    if (tl != NULL) {
+        tl = tlib_readd(tl, hash, mi, mi_size, content,
+            benc_dget_str(args, "name", NULL));
+    } else {
+        tl = tlib_add(hash, mi, mi_size, content,
+            benc_dget_str(args, "name", NULL));
+    }
     return write_add_buffer(cli, tl->num);
 }
 
@@ -270,7 +279,7 @@ cmd_del(struct cli *cli, int argc, const char *args)
     else
         return IPC_COMMERR;
 
-    if (tl == NULL)
+    if (tl == NULL || torrent_haunting(tl))
         ret = write_code_buffer(cli, IPC_ENOTENT);
     else {
         ret = write_code_buffer(cli, IPC_OK);
@@ -300,9 +309,9 @@ cmd_start(struct cli *cli, int argc, const char *args)
     else
         return IPC_COMMERR;
 
-    if (tl == NULL)
+    if (tl == NULL || torrent_haunting(tl))
         code = IPC_ENOTENT;
-    else if (tl->tp != NULL)
+    else if (!torrent_startable(tl))
         code = IPC_ETACTIVE;
     else
         if ((code = torrent_start(tl)) == IPC_OK)
@@ -324,9 +333,9 @@ cmd_stop(struct cli *cli, int argc, const char *args)
     else
         return IPC_COMMERR;
 
-    if (tl == NULL)
+    if (tl == NULL || torrent_haunting(tl))
         return write_code_buffer(cli, IPC_ENOTENT);
-    else if (tl->tp == NULL)
+    else if (!torrent_active(tl))
         return write_code_buffer(cli, IPC_ETINACTIVE);
     else  {
         // Stopping a torrent may trigger exit so we need to reply before.
@@ -340,12 +349,11 @@ cmd_stop(struct cli *cli, int argc, const char *args)
 static int
 cmd_stop_all(struct cli *cli, int argc, const char *args)
 {
-    struct torrent *tp;
+    struct torrent *tp, *next;
     int ret = write_code_buffer(cli, IPC_OK);
     active_clear();
-    BTPDQ_FOREACH(tp, torrent_get_all(), entry)
-        if (tp->state != T_STOPPING)
-            torrent_stop(tp, 0);
+    BTPDQ_FOREACH_MUTABLE(tp, torrent_get_all(), entry, next)
+        torrent_stop(tp, 0);
     return ret;
 }
 
@@ -354,11 +362,8 @@ cmd_die(struct cli *cli, int argc, const char *args)
 {
     int err = write_code_buffer(cli, IPC_OK);
     if (!btpd_is_stopping()) {
-        int grace_seconds = -1;
-        if (argc == 1 && benc_isint(args))
-            grace_seconds = benc_int(args, NULL);
         btpd_log(BTPD_L_BTPD, "Someone wants me dead.\n");
-        btpd_shutdown(grace_seconds);
+        btpd_shutdown();
     }
     return err;
 }
@@ -449,6 +454,13 @@ client_connection_cb(int sd, short type, void *arg)
     btpd_ev_new(&cli->read, cli->sd, EV_READ, cli_read_cb, cli);
 }
 
+void
+ipc_shutdown(void)
+{
+    btpd_ev_del(&m_cli_incoming);
+    close(m_listen_sd);
+}
+
 void
 ipc_init(void)
 {
@@ -477,4 +489,5 @@ ipc_init(void)
     set_nonblocking(sd);
 
     btpd_ev_new(&m_cli_incoming, sd, EV_READ, client_connection_cb, NULL);
+    m_listen_sd = sd;
 }
diff --git a/btpd/main.c b/btpd/main.c
index efa0e5d..c3cd395 100644
--- a/btpd/main.c
+++ b/btpd/main.c
@@ -5,6 +5,7 @@
 
 int btpd_daemon_phase = 2;
 int first_btpd_comm[2];
+int pidfd;
 
 void
 first_btpd_exit(char code)
@@ -15,7 +16,7 @@ first_btpd_exit(char code)
 }
 
 static void
-writepid(int pidfd)
+writepid(void)
 {
     int nw;
     char pidtxt[100];
@@ -28,7 +29,6 @@ static void
 setup_daemon(int daemonize, const char *dir)
 {
     char c;
-    int pidfd;
     pid_t pid;
     struct timespec ts;
 
@@ -91,7 +91,7 @@ setup_daemon(int daemonize, const char *dir)
     if (lockf(pidfd, F_TLOCK, 0) == -1)
         btpd_err("Another instance of btpd is probably running in %s.\n", dir);
 
-    writepid(pidfd);
+    writepid();
 }
 
 static void
diff --git a/btpd/net.c b/btpd/net.c
index 0112abe..2208223 100644
--- a/btpd/net.c
+++ b/btpd/net.c
@@ -14,6 +14,7 @@ struct net_listener {
     struct fdev ev;
 };
 
+static int m_nlisteners;
 static struct net_listener *m_net_listeners;
 
 unsigned net_npeers;
@@ -668,6 +669,15 @@ net_af_spec(void)
         return AF_INET6;
 }
 
+void
+net_shutdown(void)
+{
+    for (int i = 0; i < m_nlisteners; i++) {
+        btpd_ev_del(&m_net_listeners[i].ev);
+        close(m_net_listeners[i].sd);
+    }
+}
+
 void
 net_init(void)
 {
@@ -699,6 +709,7 @@ net_init(void)
     net_ipv6 = found_ipv6;
     if (!net_ipv4 && !net_ipv6)
         btpd_err("no usable address found. wrong use of -4/-6 perhaps.\n");
+    m_nlisteners = count;
     m_net_listeners = btpd_calloc(count, sizeof(*m_net_listeners));
     for (ai = res; ai != NULL; ai = ai->ai_next) {
         count--;
diff --git a/btpd/tlib.c b/btpd/tlib.c
index e68c341..bd4fbc6 100644
--- a/btpd/tlib.c
+++ b/btpd/tlib.c
@@ -65,7 +65,7 @@ tlib_del(struct tlib *tl)
     char path[PATH_MAX];
     DIR *dir;
     struct dirent *de;
-    assert(tl->tp == NULL);
+    assert(tl->tp == NULL || tl->tp->state == T_GHOST);
     snprintf(path, PATH_MAX, "torrents/%s", bin2hex(tl->hash, relpath, 20));
     if ((dir = opendir(path)) != NULL) {
         while ((de = readdir(dir)) != NULL) {
@@ -78,7 +78,8 @@ tlib_del(struct tlib *tl)
     }
     snprintf(path, PATH_MAX, "torrents/%s", relpath);
     remove(path);
-    tlib_kill(tl);
+    if (tl->tp == NULL)
+        tlib_kill(tl);
     return 0;
 }
 
@@ -257,6 +258,19 @@ tlib_add(const uint8_t *hash, const char *mi, size_t mi_size,
     return tl;
 }
 
+struct tlib *
+tlib_readd(struct tlib *tl, const uint8_t *hash, const char *mi,
+    size_t mi_size, const char *content, char *name)
+{
+    struct tlib *tln;
+    struct torrent *tp = tl->tp;
+    tp->delete = 0;
+    tlib_kill(tl);
+    tln = tlib_add(hash, mi, mi_size, content, name);
+    tln->tp = tp;
+    return tln;
+}
+
 static int
 num_test(const void *k1, const void *k2)
 {
diff --git a/btpd/tlib.h b/btpd/tlib.h
index 0147c36..51eacbb 100644
--- a/btpd/tlib.h
+++ b/btpd/tlib.h
@@ -26,7 +26,10 @@ void tlib_put_all(struct tlib **v);
 
 struct tlib *tlib_add(const uint8_t *hash, const char *mi, size_t mi_size,
     const char *content, char *name);
+struct tlib *tlib_readd(struct tlib *tl, const uint8_t *hash, const char *mi,
+    size_t mi_size, const char *content, char *name);
 int tlib_del(struct tlib *tl);
+void tlib_kill(struct tlib *tl);
 
 void tlib_update_info(struct tlib *tl, int only_file);
 
diff --git a/btpd/torrent.c b/btpd/torrent.c
index c48e844..0ec0b65 100644
--- a/btpd/torrent.c
+++ b/btpd/torrent.c
@@ -4,6 +4,7 @@
 
 #define SAVE_INTERVAL 300
 
+static unsigned m_nghosts;
 static unsigned m_ntorrents;
 static struct torrent_tq m_torrents = BTPDQ_HEAD_INITIALIZER(m_torrents);
 
@@ -22,6 +23,12 @@ torrent_count(void)
     return m_ntorrents;
 }
 
+unsigned
+torrent_ghosts(void)
+{
+    return m_nghosts;
+}
+
 struct torrent *
 torrent_by_num(unsigned num)
 {
@@ -71,12 +78,41 @@ torrent_block_size(struct torrent *tp, uint32_t piece, uint32_t nblocks,
     }
 }
 
+static void
+torrent_kill(struct torrent *tp)
+{
+    assert(m_ntorrents > 0);
+    assert(!(net_active(tp) || cm_active(tp)));
+    if (tp->state == T_GHOST)
+        m_nghosts--;
+    m_ntorrents--;
+    BTPDQ_REMOVE(&m_torrents, tp, entry);
+    if (tp->delete)
+        tlib_kill(tp->tl);
+    else
+        tp->tl->tp = NULL;
+    tr_kill(tp);
+    net_kill(tp);
+    cm_kill(tp);
+    mi_free_files(tp->nfiles, tp->files);
+    if (m_savetp == tp)
+        if ((m_savetp = BTPDQ_NEXT(tp, entry)) == NULL)
+            m_savetp = BTPDQ_FIRST(&m_torrents);
+    free(tp);
+}
+
 enum ipc_err
 torrent_start(struct tlib *tl)
 {
     struct torrent *tp;
     char *mi;
 
+    if (tl->tp != NULL) {
+        assert(torrent_startable(tl));
+        torrent_kill(tl->tp);
+        tl->tp = NULL;
+    }
+
     if (tl->dir == NULL)
         return IPC_EBADTENT;
 
@@ -111,25 +147,16 @@ torrent_start(struct tlib *tl)
     return IPC_OK;
 }
 
-static void
-torrent_kill(struct torrent *tp)
+static
+void become_ghost(struct torrent *tp)
 {
     btpd_log(BTPD_L_BTPD, "Stopped torrent '%s'.\n", torrent_name(tp));
-    assert(m_ntorrents > 0);
-    assert(!(tr_active(tp) || net_active(tp) || cm_active(tp)));
-    m_ntorrents--;
-    BTPDQ_REMOVE(&m_torrents, tp, entry);
-    tp->tl->tp = NULL;
+    tp->state = T_GHOST;
     if (tp->delete)
         tlib_del(tp->tl);
-    tr_kill(tp);
-    net_kill(tp);
-    cm_kill(tp);
-    mi_free_files(tp->nfiles, tp->files);
-    if (m_savetp == tp)
-        if ((m_savetp = BTPDQ_NEXT(tp, entry)) == NULL)
-            m_savetp = BTPDQ_FIRST(&m_torrents);
-    free(tp);
+    else
+        tlib_update_info(tp->tl, 0);
+    m_nghosts++;
 }
 
 void
@@ -148,10 +175,13 @@ torrent_stop(struct torrent *tp, int delete)
             tr_stop(tp);
         if (cm_active(tp))
             cm_stop(tp);
-        if (!delete)
-            tlib_update_info(tp->tl, 0);
+        if (!cm_active(tp)) {
+            become_ghost(tp);
+            if (!tr_active(tp))
+                torrent_kill(tp);
+        }
         break;
-    case T_STOPPING:
+    default:
         break;
     }
 }
@@ -187,7 +217,11 @@ torrent_on_tick(struct torrent *tp)
         }
         break;
     case T_STOPPING:
-        if (!(cm_active(tp) || tr_active(tp)))
+        if (cm_active(tp))
+            break;
+        become_ghost(tp);
+    case T_GHOST:
+        if (!tr_active(tp))
             torrent_kill(tp);
         break;
     default:
@@ -213,3 +247,21 @@ torrent_on_tick_all(void)
         }
     }
 }
+
+int
+torrent_active(struct tlib *tl)
+{
+    return tl->tp != NULL && tl->tp->state != T_GHOST;
+}
+
+int
+torrent_startable(struct tlib *tl)
+{
+    return tl->tp == NULL || (tl->tp->state == T_GHOST && !tl->tp->delete);
+}
+
+int
+torrent_haunting(struct tlib *tl)
+{
+    return tl->tp != NULL && tl->tp->delete && tl->tp->state == T_GHOST;
+}
diff --git a/btpd/torrent.h b/btpd/torrent.h
index e8eee4c..273b32f 100644
--- a/btpd/torrent.h
+++ b/btpd/torrent.h
@@ -8,7 +8,8 @@ enum torrent_state {
     T_STARTING,
     T_LEECH,
     T_SEED,
-    T_STOPPING
+    T_STOPPING,
+    T_GHOST
 };
 
 struct torrent {
@@ -34,6 +35,7 @@ struct torrent {
 BTPDQ_HEAD(torrent_tq, torrent);
 
 unsigned torrent_count(void);
+unsigned torrent_ghosts(void);
 const struct torrent_tq *torrent_get_all(void);
 struct torrent *torrent_by_num(unsigned num);
 struct torrent *torrent_by_hash(const uint8_t *hash);
@@ -41,6 +43,10 @@ struct torrent *torrent_by_hash(const uint8_t *hash);
 enum ipc_err torrent_start(struct tlib *tl);
 void torrent_stop(struct torrent *tp, int delete);
 
+int torrent_active(struct tlib *tl);
+int torrent_haunting(struct tlib *tl);
+int torrent_startable(struct tlib *tl);
+
 off_t torrent_piece_size(struct torrent *tp, uint32_t piece);
 uint32_t torrent_piece_blocks(struct torrent *tp, uint32_t piece);
 uint32_t torrent_block_size(struct torrent *tp, uint32_t piece,
diff --git a/cli/kill.c b/cli/kill.c
index 9ae57f1..1d727bb 100644
--- a/cli/kill.c
+++ b/cli/kill.c
@@ -6,12 +6,7 @@ usage_kill(void)
     printf(
         "Shutdown btpd.\n"
         "\n"
-        "Usage: kill [seconds]\n"
-        "\n"
-        "Arguments:\n"
-        "seconds\n"
-        "\tThe number of seconds btpd waits before giving up on unresponsive\n"
-        "\ttrackers.\n"
+        "Usage: kill\n"
         "\n"
         );
     exit(1);
@@ -20,18 +15,12 @@ usage_kill(void)
 void
 cmd_kill(int argc, char **argv)
 {
-    int seconds = -1;
     enum ipc_err code;
-    char *endptr;
 
-    if (argc == 2) {
-        seconds = strtol(argv[1], &endptr, 10);
-        if (strlen(argv[1]) > endptr - argv[1] || seconds < 0)
-            usage_kill();
-    } else if (argc > 2)
+    if (argc > 1)
         usage_kill();
 
     btpd_connect();
-    if ((code = btpd_die(ipc, seconds)) != 0)
+    if ((code = btpd_die(ipc)) != 0)
         diemsg("command failed (%s).\n", ipc_strerror(code));
 }
diff --git a/misc/btpd_if.c b/misc/btpd_if.c
index f01cab9..a62daba 100644
--- a/misc/btpd_if.c
+++ b/misc/btpd_if.c
@@ -155,13 +155,10 @@ ipc_buf_req_code(struct ipc *ipc, struct iobuf *iob)
 }
 
 enum ipc_err
-btpd_die(struct ipc *ipc, int seconds)
+btpd_die(struct ipc *ipc)
 {
     struct iobuf iob = iobuf_init(16);
-    if (seconds >= 0)
-        iobuf_print(&iob, "l3:diei%dee", seconds);
-    else
-        iobuf_swrite(&iob, "l3:diee");
+    iobuf_swrite(&iob, "l3:diee");
     return ipc_buf_req_code(ipc, &iob);
 }
 
diff --git a/misc/btpd_if.h b/misc/btpd_if.h
index 0879bd4..526e5c3 100644
--- a/misc/btpd_if.h
+++ b/misc/btpd_if.h
@@ -80,7 +80,7 @@ enum ipc_err btpd_del(struct ipc *ipc, struct ipc_torrent *tp);
 enum ipc_err btpd_start(struct ipc *ipc, struct ipc_torrent *tp);
 enum ipc_err btpd_stop(struct ipc *ipc, struct ipc_torrent *tp);
 enum ipc_err btpd_stop_all(struct ipc *ipc);
-enum ipc_err btpd_die(struct ipc *ipc, int seconds);
+enum ipc_err btpd_die(struct ipc *ipc);
 enum ipc_err btpd_get(struct ipc *ipc, enum ipc_dval *keys, size_t nkeys,
     tget_cb_t cb, void *arg);
 enum ipc_err btpd_tget(struct ipc *ipc, struct ipc_torrent *tps, size_t ntps,