diff --git a/c/opendht.cpp b/c/opendht.cpp
index 996282ef320c694ec6af88cfe901ef77f8f3dabf..ced1157ab2a221d83cb3610325906cec76a6b300 100644
--- a/c/opendht.cpp
+++ b/c/opendht.cpp
@@ -265,34 +265,44 @@ void dht_runner_delete(dht_runner* runner) {
     delete reinterpret_cast<dht::DhtRunner*>(runner);
 }
 
-void dht_runner_run(dht_runner* r, in_port_t port) {
+int dht_runner_run(dht_runner* r, in_port_t port) {
     auto runner = reinterpret_cast<dht::DhtRunner*>(r);
-    runner->run(port, {}, true);
+    try {
+        runner->run(port, {}, true);
+    } catch(...) {
+        return ENOTCONN;
+    }
+    return 0;
 }
 
-void dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config* conf) {
+int dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config* conf) {
     auto runner = reinterpret_cast<dht::DhtRunner*>(r);
-    dht::DhtRunner::Config config;
-    config.dht_config.node_config.is_bootstrap = conf->dht_config.node_config.is_bootstrap;
-    config.dht_config.node_config.maintain_storage = conf->dht_config.node_config.maintain_storage;
-    config.dht_config.node_config.node_id = *reinterpret_cast<const dht::InfoHash*>(&conf->dht_config.node_config.node_id);
-    config.dht_config.node_config.network = conf->dht_config.node_config.network;
-    config.dht_config.node_config.persist_path = conf->dht_config.node_config.persist_path
-        ? std::string(conf->dht_config.node_config.persist_path) : std::string{};
-
-    if (conf->dht_config.id.privatekey)
-        config.dht_config.id.first = *reinterpret_cast<const PrivkeySp*>(conf->dht_config.id.privatekey);
-
-    if (conf->dht_config.id.certificate)
-        config.dht_config.id.second = *reinterpret_cast<const CertSp*>(conf->dht_config.id.certificate);
-
-    config.threaded = conf->threaded;
-    config.proxy_server = conf->proxy_server ? std::string(conf->proxy_server) : std::string{};
-    config.push_node_id = conf->push_node_id ? std::string(conf->push_node_id) : std::string{};
-    config.push_token = conf->push_token ? std::string(conf->push_token) : std::string{};
-    config.peer_discovery = conf->peer_discovery;
-    config.peer_publish = conf->peer_publish;
-    runner->run(port, config);
+    try {
+        dht::DhtRunner::Config config;
+        config.dht_config.node_config.is_bootstrap = conf->dht_config.node_config.is_bootstrap;
+        config.dht_config.node_config.maintain_storage = conf->dht_config.node_config.maintain_storage;
+        config.dht_config.node_config.node_id = *reinterpret_cast<const dht::InfoHash*>(&conf->dht_config.node_config.node_id);
+        config.dht_config.node_config.network = conf->dht_config.node_config.network;
+        config.dht_config.node_config.persist_path = conf->dht_config.node_config.persist_path
+            ? std::string(conf->dht_config.node_config.persist_path) : std::string{};
+
+        if (conf->dht_config.id.privatekey)
+            config.dht_config.id.first = *reinterpret_cast<const PrivkeySp*>(conf->dht_config.id.privatekey);
+
+        if (conf->dht_config.id.certificate)
+            config.dht_config.id.second = *reinterpret_cast<const CertSp*>(conf->dht_config.id.certificate);
+
+        config.threaded = conf->threaded;
+        config.proxy_server = conf->proxy_server ? std::string(conf->proxy_server) : std::string{};
+        config.push_node_id = conf->push_node_id ? std::string(conf->push_node_id) : std::string{};
+        config.push_token = conf->push_token ? std::string(conf->push_token) : std::string{};
+        config.peer_discovery = conf->peer_discovery;
+        config.peer_publish = conf->peer_publish;
+        runner->run(port, config);
+    } catch(...) {
+        return ENOTCONN;
+    }
+    return 0;
 }
 
 void dht_runner_ping(dht_runner* r, struct sockaddr* addr, socklen_t addr_len) {
diff --git a/c/opendht_c.h b/c/opendht_c.h
index 88d02e303f15849a3ae19dddf37bacf6c4986164..7ca76ae64185c87c59c95579171ab18d5a34a630 100644
--- a/c/opendht_c.h
+++ b/c/opendht_c.h
@@ -137,8 +137,10 @@ struct OPENDHT_C_PUBLIC dht_runner;
 typedef struct dht_runner dht_runner;
 OPENDHT_C_PUBLIC dht_runner* dht_runner_new(void);
 OPENDHT_C_PUBLIC void dht_runner_delete(dht_runner* runner);
-OPENDHT_C_PUBLIC void dht_runner_run(dht_runner* runner, in_port_t port);
-OPENDHT_C_PUBLIC void dht_runner_run_config(dht_runner* runner, in_port_t port, const dht_runner_config* config);
+/* Returns 0 on success, standard error code on failure */
+OPENDHT_C_PUBLIC int dht_runner_run(dht_runner* runner, in_port_t port);
+/* Returns 0 on success, standard error code on failure */
+OPENDHT_C_PUBLIC int dht_runner_run_config(dht_runner* runner, in_port_t port, const dht_runner_config* config);
 OPENDHT_C_PUBLIC void dht_runner_ping(dht_runner* runner, struct sockaddr* addr, socklen_t addr_len);
 OPENDHT_C_PUBLIC void dht_runner_bootstrap(dht_runner* runner, const char* host, const char* service);
 OPENDHT_C_PUBLIC void dht_runner_get(dht_runner* runner, const dht_infohash* hash, dht_get_cb cb, dht_done_cb done_cb, void* cb_user_data);