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
This commit is contained in:
Viktor Tarasov 2012-05-29 19:44:54 +02:00
parent 954d0b9375
commit be81263d8e
3 changed files with 63 additions and 11 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;