diff --git a/libisoburn/libisoburn.ver b/libisoburn/libisoburn.ver index afc554a9..176ee8df 100644 --- a/libisoburn/libisoburn.ver +++ b/libisoburn/libisoburn.ver @@ -124,6 +124,7 @@ Xorriso_destroy; Xorriso_dialog; Xorriso_eval_problem_status; Xorriso_execute_option; +Xorriso_fetch_outlists; Xorriso_get_problem_status; Xorriso_interpreter; Xorriso_lst_destroy_all; diff --git a/xorriso/base_obj.c b/xorriso/base_obj.c index 85c4923c..963563a9 100644 --- a/xorriso/base_obj.c +++ b/xorriso/base_obj.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef HAVE_STDINT_H #include @@ -317,6 +318,8 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->info_msglists[i]= NULL; m->msglist_flags[i]= 0; } + m->lib_msg_queue_lock_ini= 0; + m->result_msglists_lock_ini= 0; m->msglist_stackfill= 0; m->status_history_max= Xorriso_status_history_maX; m->scsi_log= 0; @@ -433,6 +436,14 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) if(ret <= 0) goto failure; Xorriso_preparer_string(m, m->preparer_id, 1); /* avoids library calls */ + ret= pthread_mutex_init(&(m->lib_msg_queue_lock), NULL); + if(ret != 0) + goto failure; + m->lib_msg_queue_lock_ini= 1; + ret= pthread_mutex_init(&(m->result_msglists_lock), NULL); + if(ret != 0) + goto failure; + m->result_msglists_lock_ini= 1; if(leafname != NULL) free(leafname); @@ -513,7 +524,11 @@ int Xorriso_destroy(struct XorrisO **xorriso, int flag) for(i= 0; i < Xorriso_max_appended_partitionS; i++) if(m->appended_partitions[i] != NULL) free(m->appended_partitions[i]); - + if(m->lib_msg_queue_lock_ini) + pthread_mutex_destroy(&(m->lib_msg_queue_lock)); + if(m->result_msglists_lock_ini) + pthread_mutex_destroy(&(m->result_msglists_lock)); + Xorriso_detach_libraries(m, flag&1); free((char *) m); diff --git a/xorriso/lib_mgt.c b/xorriso/lib_mgt.c index b302645a..669d1dfd 100644 --- a/xorriso/lib_mgt.c +++ b/xorriso/lib_mgt.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef HAVE_STDINT_H #include @@ -469,15 +470,26 @@ cannot:; int Xorriso_process_msg_queues(struct XorrisO *xorriso, int flag) { int ret, error_code= 0, os_errno= 0, count= 0, pass, imgid, tunneled; - int name_prefix_code; + int name_prefix_code, locked= 0, uret; char severity[80]; #ifdef Xorriso_with_libjtE char *msg; #endif - if(!xorriso->libs_are_started) - return(1); + if(!xorriso->libs_are_started) { + ret= 1; goto ex; + } + + ret= pthread_mutex_lock(&(xorriso->lib_msg_queue_lock)); + if(ret != 0) { + Xorriso_msgs_submit(xorriso, 0, + "Cannot aquire mutex lock for processing library message queues", + errno, "FATAL", 0); + ret= -1; goto ex; + } + locked= 1; + for(pass= 0; pass< 3; pass++) { while(1) { tunneled= 0; @@ -536,6 +548,17 @@ int Xorriso_process_msg_queues(struct XorrisO *xorriso, int flag) count); Xorriso_info(xorriso, 0); } + ret= 1; +ex:; + if(locked) { + uret= pthread_mutex_unlock(&(xorriso->lib_msg_queue_lock)); + if(uret != 0) { + Xorriso_msgs_submit(xorriso, 0, + "Cannot release mutex lock for processing library message queues", + errno, "FATAL", 0); + ret= -1; + } + } return(1); } diff --git a/xorriso/text_io.c b/xorriso/text_io.c index f8aff6bb..acc37c3b 100644 --- a/xorriso/text_io.c +++ b/xorriso/text_io.c @@ -23,6 +23,8 @@ #include #include #include +#include + /* for -charset */ #include @@ -520,6 +522,68 @@ ex:; } +static int Xorriso_lock_outlists(struct XorrisO *xorriso, int flag) +{ + int ret; + static int complaints= 0, complaint_limit= 5; + + ret= pthread_mutex_lock(&(xorriso->result_msglists_lock)); + if(ret != 0) { + /* Cannot report failure through the failing message output system */ + complaints++; + if(complaints < complaint_limit) + fprintf(stderr, + "xorriso : pthread_mutex_lock() for outlists returns %d\n", + ret); + return(-1); + } + return(1); +} + + +static int Xorriso_unlock_outlists(struct XorrisO *xorriso, int flag) +{ + int ret; + static int complaints= 0, complaint_limit= 5; + + ret= pthread_mutex_unlock(&(xorriso->result_msglists_lock)); + if(ret != 0) { + /* Cannot report failure through the failing message output system */ + complaints++; + if(complaints < complaint_limit) + fprintf(stderr, + "xorriso : pthread_mutex_unlock() for outlists returns %d\n", + ret); + return(0); + } + return(1); +} + + +static int Xorriso_write_to_msglist(struct XorrisO *xorriso, + struct Xorriso_lsT **xorriso_msglist, + char *text, int flag) +{ + int ret; + struct Xorriso_lsT *msglist; + + ret= Xorriso_lock_outlists(xorriso, 0); + if(ret <= 0) + return(-1); + msglist= *xorriso_msglist; + ret= Xorriso_lst_append_binary(&msglist, text, strlen(text) + 1, 0); + if(ret <= 0) { + ret= -1; goto ex; + } + if(*xorriso_msglist == NULL) + *xorriso_msglist= msglist; + ret= 1; +ex:; + Xorriso_unlock_outlists(xorriso, 0); + return(ret); +} + + int Xorriso_write_to_channel(struct XorrisO *xorriso, char *in_text, int channel_no, int flag) /* @@ -534,7 +598,6 @@ bit15= with bit1 to bit3: close depicted log file int ret= 1, info_redirected= 0, result_redirected= 0; char prefix[16]; FILE *logfile_fp, *pktlog_fp; - struct Xorriso_lsT *msglist; static int num_channels= 4; static char channel_prefixes[4][4]= {".","R","I","M"}; @@ -610,22 +673,20 @@ bit15= with bit1 to bit3: close depicted log file } if(result_redirected) { if(channel_no==1 || channel_no==3) { - msglist= xorriso->result_msglists[xorriso->msglist_stackfill - 1]; - ret= Xorriso_lst_append_binary(&msglist, text, strlen(text) + 1, 0); + ret= Xorriso_write_to_msglist(xorriso, + &(xorriso->result_msglists[xorriso->msglist_stackfill - 1]), + text, 0); if(ret <= 0) - {ret= -1; goto ex;} - if(xorriso->result_msglists[xorriso->msglist_stackfill - 1] == NULL) - xorriso->result_msglists[xorriso->msglist_stackfill - 1]= msglist; + { ret= -1; goto ex; } } } if(info_redirected) { if(channel_no==2 || channel_no==3) { - msglist= xorriso->info_msglists[xorriso->msglist_stackfill - 1]; - ret= Xorriso_lst_append_binary(&msglist, text, strlen(text) + 1, 0); + ret= Xorriso_write_to_msglist(xorriso, + &(xorriso->info_msglists[xorriso->msglist_stackfill - 1]), + text, 0); if(ret <= 0) - {ret= -1; goto ex;} - if(xorriso->info_msglists[xorriso->msglist_stackfill - 1] == NULL) - xorriso->info_msglists[xorriso->msglist_stackfill - 1]= msglist; + { ret= -1; goto ex; } } } if((channel_no == 1 && result_redirected) || @@ -718,10 +779,17 @@ ex: int Xorriso_push_outlists(struct XorrisO *xorriso, int *stack_handle, int flag) { + int ret, locked= 0; + + ret= Xorriso_lock_outlists(xorriso, 0); + if(ret != 0) + {ret= -1; goto ex;} + locked= 1; + if(xorriso->msglist_stackfill + 1 >= Xorriso_max_outlist_stacK) { Xorriso_msgs_submit(xorriso, 0, "Overflow of message output redirection stack", 0, "FATAL", 0); - return(-1); + ret= -1; goto ex; } if((flag & 3) == 0) flag|= 3; @@ -730,21 +798,74 @@ int Xorriso_push_outlists(struct XorrisO *xorriso, int *stack_handle, xorriso->info_msglists[xorriso->msglist_stackfill - 1]= NULL; xorriso->msglist_flags[xorriso->msglist_stackfill - 1]= flag & 3; *stack_handle= xorriso->msglist_stackfill - 1; + ret= 1; +ex:; + if(locked) + Xorriso_unlock_outlists(xorriso, 0); + return(ret); return(1); } +int Xorriso_fetch_outlists(struct XorrisO *xorriso, int stack_handle, + struct Xorriso_lsT **result_list, + struct Xorriso_lsT **info_list, int flag) +{ + int ret, locked= 0; + + ret= Xorriso_process_msg_queues(xorriso, 0); + if(ret <= 0) + goto ex; + if((flag & 3) == 0) + flag|= 3; + + ret= Xorriso_lock_outlists(xorriso, 0); + if(ret != 0) + {ret= -1; goto ex;} + locked= 1; + + if(stack_handle == -1) + stack_handle= xorriso->msglist_stackfill - 1; + if(stack_handle < 0 || stack_handle >= xorriso->msglist_stackfill) { + Xorriso_msgs_submit(xorriso, 0, + "Program error: Wrong message output redirection stack handle", + 0, "FATAL", 0); + ret= -1; goto ex; + } + + if(flag & 1) { + *result_list= xorriso->result_msglists[stack_handle]; + xorriso->result_msglists[stack_handle]= NULL; + } + if(flag & 2) { + *info_list= xorriso->info_msglists[stack_handle]; + xorriso->info_msglists[stack_handle]= NULL; + } + + ret= 1; +ex:; + if(locked) + Xorriso_unlock_outlists(xorriso, 0); + return(ret); +} + + int Xorriso_pull_outlists(struct XorrisO *xorriso, int stack_handle, struct Xorriso_lsT **result_list, struct Xorriso_lsT **info_list, int flag) { - int i; + int i, ret, locked= 0; + + ret= Xorriso_lock_outlists(xorriso, 0); + if(ret != 0) + {ret= -1; goto ex;} + locked= 1; if(stack_handle < 0 || stack_handle >= xorriso->msglist_stackfill) { Xorriso_msgs_submit(xorriso, 0, "Program error: Wrong message output redirection stack handle", 0, "FATAL", 0); - return(-1); + ret= -1; goto ex; } *result_list= xorriso->result_msglists[stack_handle]; *info_list= xorriso->info_msglists[stack_handle]; @@ -753,7 +874,11 @@ int Xorriso_pull_outlists(struct XorrisO *xorriso, int stack_handle, xorriso->info_msglists[i - 1]= xorriso->info_msglists[i]; } xorriso->msglist_stackfill--; - return(1); + ret= 1; +ex:; + if(locked) + Xorriso_unlock_outlists(xorriso, 0); + return(ret); } @@ -972,26 +1097,12 @@ int Xorriso_msgs_submit(struct XorrisO *xorriso, xorriso->info_text[li+lt]= '\n'; xorriso->info_text[li+lt+1]= 0; -#ifdef NIX - - /* <<< */ - Xorriso_info(xorriso,4|(flag&3)); - if(os_errno>0) { - sprintf(xorriso->info_text, "%s%s : %s\n", - pfx_list[(flag>>2)&15], sev_text, strerror(os_errno)); - Xorriso_info(xorriso,4|(flag&3)); - } - -#else - if(os_errno>0) { sprintf(xorriso->info_text + strlen(xorriso->info_text) - 1, " : %s\n", strerror(os_errno)); } Xorriso_info(xorriso,4|(flag&3)); -#endif - return(1); } diff --git a/xorriso/xorriso.h b/xorriso/xorriso.h index bedabf77..b93ea6a7 100644 --- a/xorriso/xorriso.h +++ b/xorriso/xorriso.h @@ -27,6 +27,13 @@ @since major.minor.micro If this mark is missing, then the feature was present before release 0.5.8. + Please note that struct XorrisO and its API calls are _not_ thread-safe in + general. It is not permissible to run two API calls on the same + XorrisO object concurrently. + The only exception is + Xorriso_fetch_outlists() + in order to learn about the ongoing text output of other API calls. + There is a lower level of API which consists of libisofs.h, libburn.h and libisoburn.h. One should not mix those calls with the ones of xorriso.h . @@ -585,6 +592,37 @@ int Xorriso_push_outlists(struct XorrisO *xorriso, int *stack_handle, int flag); +/** Obtain the currently collected text messages of redirected info and + result channel. + The messages are handed out as two lists. Both lists have to be disposed + via Xorriso_lst_destroy_all() when they are no longer needed. + The message lists are either NULL or represented by their first + Xorriso_lsT item. + + This call is safe for being used by a concurrent thread while a + xorriso API call is being executed on the same struct XorrisO. + In such a situation, it should not be used with high frequency in order + not to hamper the ongoing xorriso operation by blocking its message + output facility. Ten times per second should be enough. + + @since 1.2.6 + @param xorriso The environment handle + @param stack_handle An id number returned by Xorriso_push_outlists() + and not yet revoked by Xorriso_pull_outlists(). + Submit -1 to address the most recent valid id. + @param result_list Result and mark messages (usually directed to stdout) + @param info_list Info and mark messages (usually directed to stderr) + @param flag Bitfield for control purposes + bit0= fetch result channel + bit1= fetch info channel + If bit0 and bit1 are 0, both channels get fetched. + @return 1 on success, <=0 if failure +*/ +int Xorriso_fetch_outlists(struct XorrisO *xorriso, int stack_handle, + struct Xorriso_lsT **result_list, + struct Xorriso_lsT **info_list, int flag); + + /** Disable the redirection given by stack_handle. If it was the current receiver of messages then switch output to the next older redirection resp. to the normal channels if no redirections are stacked any more. @@ -594,7 +632,9 @@ int Xorriso_push_outlists(struct XorrisO *xorriso, int *stack_handle, The message lists are either NULL or represented by their first Xorriso_lsT item. @param xorriso The environment handle - @param stack_handle The id number returned by Xorriso_push_outlists() + @param stack_handle An id number returned by Xorriso_push_outlists() + and not yet revoked by Xorriso_pull_outlists(). + This handle is invalid after the call. @param result_list Result and mark messages (usually directed to stdout) @param info_list Info and mark messages (usually directed to stderr) @param flag unused yet, submit 0 diff --git a/xorriso/xorriso_private.h b/xorriso/xorriso_private.h index e5d499d3..84adab58 100644 --- a/xorriso/xorriso_private.h +++ b/xorriso/xorriso_private.h @@ -561,6 +561,11 @@ struct XorrisO { /* the global context of xorriso */ */ int msglist_stackfill; + int lib_msg_queue_lock_ini; + int result_msglists_lock_ini; + pthread_mutex_t lib_msg_queue_lock; + pthread_mutex_t result_msglists_lock; + int status_history_max; /* for -status long_history */ /* 0= no logging of SCSI commands, 1= to stderr */ diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index f7aff236..dd2db044 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2012.09.09.181723" +#define Xorriso_timestamP "2012.09.11.092703"