From be81263d8e34d84c71e68ed2d39b02f3f3e7bf25 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Tue, 29 May 2012 19:44:54 +0200 Subject: [PATCH] log: config option to reopen debug file at every debug log ... To be used in windows: "In Windows, file handles can not be shared between DLL-s, each DLL has a separate file handle table. For that reason reopen debug file before every debug message." sc_context_repair() procedure from Hunter William "Workaround some threading and data lifetime issues when card handle changes and need to re-associate card" http://www.opensc-project.org/pipermail/opensc-devel/2011-December/017445.html --- src/libopensc/ctx.c | 49 ++++++++++++++++++++++++++++++++++++------ src/libopensc/log.c | 22 +++++++++++++++---- src/libopensc/opensc.h | 3 ++- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index 7ff3978e..c8b84b36 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -211,22 +211,39 @@ int sc_ctx_log_to_file(sc_context_t *ctx, const char* filename) return SC_SUCCESS; } -static int load_parameters(sc_context_t *ctx, scconf_block *block, - struct _sc_ctx_options *opts) + +static int +load_parameters(sc_context_t *ctx, scconf_block *block, struct _sc_ctx_options *opts) { int err = 0; const scconf_list *list; const char *val, *s_internal = "internal"; - const char *debug = NULL; - + const char *debug = NULL; + int reopen; +#ifdef _WIN32 + char expanded_val[PATH_MAX]; + DWORD expanded_len; +#endif ctx->debug = scconf_get_int(block, "debug", ctx->debug); + reopen = scconf_get_bool(block, "reopen_debug_file", 1); + debug = getenv("OPENSC_DEBUG"); if (debug) ctx->debug = atoi(debug); val = scconf_get_str(block, "debug_file", NULL); - if (val) + if (val) { +#ifdef _WIN32 + expanded_len = PATH_MAX; + expanded_len = ExpandEnvironmentStrings(val, expanded_val, expanded_len); + if (expanded_len > 0) + val = expanded_val; +#endif + if (reopen) + ctx->debug_filename = strdup(val); + sc_ctx_log_to_file(ctx, val); + } ctx->paranoid_memory = scconf_get_bool (block, "paranoid-memory", ctx->paranoid_memory); @@ -620,6 +637,24 @@ int sc_establish_context(sc_context_t **ctx_out, const char *app_name) return sc_context_create(ctx_out, &ctx_param); } +/* For multithreaded issues */ +int sc_context_repair(sc_context_t **ctx_out) +{ + /* Must already exist */ + if ((ctx_out == NULL) || (*ctx_out == NULL) || + ((*ctx_out)->app_name == NULL)) + return SC_ERROR_INVALID_ARGUMENTS; + + /* The only thing that should be shared across different contexts are the + * card drivers - so rebuild the ATR's + */ + load_card_atrs(*ctx_out); + + /* TODO: May need to re-open any card driver DLL's */ + + return SC_SUCCESS; +} + int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm) { sc_context_t *ctx; @@ -756,9 +791,11 @@ int sc_release_context(sc_context_t *ctx) scconf_free(ctx->conf); if (ctx->debug_file && (ctx->debug_file != stdout && ctx->debug_file != stderr)) fclose(ctx->debug_file); + if (ctx->debug_filename != NULL) + free(ctx->debug_filename); if (ctx->app_name != NULL) free(ctx->app_name); - list_destroy(&ctx->readers); + list_destroy(&ctx->readers); sc_mem_clear(ctx, sizeof(*ctx)); free(ctx); return SC_SUCCESS; diff --git a/src/libopensc/log.c b/src/libopensc/log.c index 4acf5638..fbb02948 100644 --- a/src/libopensc/log.c +++ b/src/libopensc/log.c @@ -97,13 +97,14 @@ static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int lin left -= r; if (file != NULL) { - r = snprintf(p, left, "[%s] %s:%d:%s: ", + r = snprintf(p, left, "[%s] %s:%d:%s: ", ctx->app_name, file, line, func ? func : ""); if (r < 0 || (unsigned int)r > sizeof(buf)) return; - } else { + } + else { r = 0; - } + } p += r; left -= r; @@ -111,6 +112,11 @@ static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int lin if (r < 0) return; +#ifdef _WIN32 + if (ctx->debug_filename) + sc_ctx_log_to_file(ctx, ctx->debug_filename); +#endif + outf = ctx->debug_file; if (outf == NULL) return; @@ -121,11 +127,19 @@ static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int lin fprintf(outf, "\n"); fflush(outf); +#ifdef _WIN32 + if (ctx->debug_filename) { + fclose(ctx->debug_file); + ctx->debug_file = NULL; + } +#endif + + return; } void _sc_debug(struct sc_context *ctx, int level, const char *format, ...) -{ +{ va_list ap; va_start(ap, format); diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index ac00223a..15b35acb 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -681,10 +681,11 @@ typedef struct sc_context { int paranoid_memory; FILE *debug_file; + char *debug_filename; char *preferred_language; list_t readers; - + struct sc_reader_driver *reader_driver; void *reader_drv_data;