Add ERR_remove_thread_state (for Android).
Change-Id: I908d207ccd3d529ec09c687effc2aeb4631127d9
Reviewed-on: https://boringssl-review.googlesource.com/1470
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 76d101a..9d29f1c 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -271,6 +271,29 @@
state->top = state->bottom = 0;
}
+void ERR_remove_thread_state(const CRYPTO_THREADID *tid) {
+ CRYPTO_THREADID current;
+ ERR_STATE *state;
+ unsigned i;
+
+ if (tid == NULL) {
+ CRYPTO_THREADID_current(¤t);
+ tid = ¤t;
+ }
+
+ err_fns_check();
+ state = ERRFN(release_state)(tid);
+ if (state == NULL) {
+ return;
+ }
+
+ for (i = 0; i < ERR_NUM_ERRORS; i++) {
+ err_clear(&state->errors[i]);
+ }
+
+ OPENSSL_free(state);
+}
+
int ERR_get_next_error_library() {
err_fns_check();
return ERRFN(get_next_library)();
diff --git a/crypto/err/err_impl.c b/crypto/err/err_impl.c
index 6544c7b..7554714 100644
--- a/crypto/err/err_impl.c
+++ b/crypto/err/err_impl.c
@@ -265,6 +265,23 @@
return state;
}
+static ERR_STATE *err_release_state(const CRYPTO_THREADID *tid) {
+ ERR_STATE pattern, *state;
+
+ CRYPTO_THREADID_cpy(&pattern.tid, tid);
+
+ CRYPTO_r_lock(CRYPTO_LOCK_ERR);
+ if (state_hash == NULL) {
+ CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+ return NULL;
+ }
+
+ state = lh_ERR_STATE_delete(state_hash, &pattern);
+ CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+
+ return state;
+}
+
static void err_shutdown(void) {
CRYPTO_w_lock(CRYPTO_LOCK_ERR);
if (error_hash) {
@@ -290,5 +307,6 @@
err_set_item,
err_del_item,
err_get_state,
+ err_release_state,
err_get_next_library,
};
diff --git a/crypto/err/err_test.c b/crypto/err/err_test.c
index adfc9d0..22cbef7 100644
--- a/crypto/err/err_test.c
+++ b/crypto/err/err_test.c
@@ -105,11 +105,18 @@
return 1;
}
+static int test_release() {
+ ERR_put_error(1, 2, 3, "test", 4);
+ ERR_remove_thread_state(NULL);
+ return 0;
+}
+
int main() {
if (!test_overflow() ||
!test_put_error() ||
!test_clear_error() ||
- !test_print()) {
+ !test_print() ||
+ !test_release()) {
return 1;
}
diff --git a/include/openssl/err.h b/include/openssl/err.h
index ddb094c..8ebd73f 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -256,6 +256,10 @@
/* ERR_clear_error clears the error queue for the current thread. */
OPENSSL_EXPORT void ERR_clear_error(void);
+/* ERR_remove_thread_state deletes the error queue for the given thread. If
+ * |tid| is NULL then the error queue for the current thread is deleted. */
+OPENSSL_EXPORT void ERR_remove_thread_state(const CRYPTO_THREADID *tid);
+
/* Custom errors. */
@@ -482,6 +486,11 @@
* never returns NULL. */
ERR_STATE *(*get_state)(void);
+ /* release_state returns the |ERR_STATE| for the given thread, or NULL if
+ * none exists. It the return value is not NULL, it also returns ownership of
+ * the |ERR_STATE| and deletes it from its data structures. */
+ ERR_STATE *(*release_state)(const CRYPTO_THREADID *tid);
+
/* get_next_library returns a unique value suitable for passing as the
* |library| to error calls. It will be distinct from all built-in library
* values. */