Introduced alternative signal handling actions

This commit is contained in:
Thomas Schmitt 2010-03-05 09:08:16 +00:00
parent b4e5afd317
commit 3519b42c14
12 changed files with 395 additions and 51 deletions

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2010.03.04.180102" #define Cdrskin_timestamP "2010.03.05.090948"

View File

@ -40,6 +40,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <signal.h>
/* /*
#include <a ssert.h> #include <a ssert.h>
@ -534,8 +535,22 @@ no_non_default_bd_re:;
static void *write_disc_worker_func(struct w_list *w) static void *write_disc_worker_func(struct w_list *w)
{ {
struct burn_drive *d = w->u.write.drive; struct burn_drive *d = w->u.write.drive;
char msg[80];
#define Libburn_protect_write_threaD 1
#ifdef Libburn_protect_write_threaD
sigset_t sigset, oldset;
/* Protect write thread from being interrupted by external signals */
sigfillset(&sigset);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGILL);
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
#endif /* Libburn_protect_write_threaD */
d->thread_pid = getpid(); d->thread_pid = getpid();
d->thread_tid = pthread_self();
d->thread_pid_valid= 1; d->thread_pid_valid= 1;
burn_disc_write_sync(w->u.write.opts, w->u.write.disc); burn_disc_write_sync(w->u.write.opts, w->u.write.disc);
d->thread_pid_valid= 0; d->thread_pid_valid= 0;
@ -545,7 +560,18 @@ static void *write_disc_worker_func(struct w_list *w)
*/ */
burn_write_opts_free(w->u.write.opts); burn_write_opts_free(w->u.write.opts);
sprintf(msg, "Write thread on drive %d ended", d->global_index);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020178,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
#ifdef Libburn_protect_write_threaD
/* (just in case it would not end with all signals blocked) */
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#endif /* Libburn_protect_write_threaD */
remove_worker(pthread_self()); remove_worker(pthread_self());
d->busy = BURN_DRIVE_IDLE;
return NULL; return NULL;
} }
@ -653,6 +679,18 @@ int burn_fifo_start(struct burn_source *source, int flag)
struct fifo_opts o; struct fifo_opts o;
struct burn_source_fifo *fs = source->data; struct burn_source_fifo *fs = source->data;
#define Libburn_protect_fifo_threaD 1
#ifdef Libburn_protect_fifo_threaD
sigset_t sigset, oldset;
/* Protect write thread from being interrupted by external signals */
sigfillset(&sigset);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGILL);
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
#endif /* Libburn_protect_fifo_threaD */
fs->is_started = -1; fs->is_started = -1;
/* create and set up ring buffer */; /* create and set up ring buffer */;
@ -668,6 +706,12 @@ int burn_fifo_start(struct burn_source *source, int flag)
add_worker(Burnworker_type_fifO, NULL, add_worker(Burnworker_type_fifO, NULL,
(WorkerFunc) fifo_worker_func, &o); (WorkerFunc) fifo_worker_func, &o);
fs->is_started = 1; fs->is_started = 1;
#ifdef Libburn_protect_fifo_threaD
/* (just in case it would not end with all signals blocked) */
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#endif /* Libburn_protect_fifo_threaD */
return 1; return 1;
} }

View File

@ -376,6 +376,7 @@ struct burn_drive *burn_drive_register(struct burn_drive *d)
d->busy = BURN_DRIVE_IDLE; d->busy = BURN_DRIVE_IDLE;
d->thread_pid = 0; d->thread_pid = 0;
d->thread_pid_valid = 0; d->thread_pid_valid = 0;
memset(&(d->thread_tid), 0, sizeof(d->thread_tid));
d->toc_entries = 0; d->toc_entries = 0;
d->toc_entry = NULL; d->toc_entry = NULL;
d->disc = NULL; d->disc = NULL;
@ -815,10 +816,22 @@ int burn_disc_erasable(struct burn_drive *d)
enum burn_drive_status burn_drive_get_status(struct burn_drive *d, enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
struct burn_progress *p) struct burn_progress *p)
{ {
/* --- Part of asynchronous signal handling --- */
/* This frequently used call may be used to react on messages from
the libburn built-in signal handler.
*/
/* ts B00225 :
If aborting with action 2:
catch control thread after it returned from signal handler.
Let it run burn_abort(4440,...)
*/
burn_init_catch_on_abort(0);
/* ts A70928 : inform control thread of signal in sub-threads */ /* ts A70928 : inform control thread of signal in sub-threads */
if (burn_global_abort_level > 0) if (burn_builtin_triggered_action < 2 && burn_global_abort_level > 0)
burn_global_abort_level++; burn_global_abort_level++;
if (burn_global_abort_level > 5) { if (burn_builtin_triggered_action < 2 && burn_global_abort_level > 5) {
if (burn_global_signal_handler == NULL) if (burn_global_signal_handler == NULL)
kill(getpid(), burn_global_abort_signum); kill(getpid(), burn_global_abort_signum);
else else
@ -828,6 +841,9 @@ enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
burn_global_abort_level = -1; burn_global_abort_level = -1;
} }
/* --- End of asynchronous signal handling --- */
if (p != NULL) { if (p != NULL) {
memcpy(p, &(d->progress), sizeof(struct burn_progress)); memcpy(p, &(d->progress), sizeof(struct burn_progress));
/* TODO: add mutex */ /* TODO: add mutex */
@ -849,9 +865,13 @@ int burn_drive_set_stream_recording(struct burn_drive *d, int recmode,
void burn_drive_cancel(struct burn_drive *d) void burn_drive_cancel(struct burn_drive *d)
{ {
/* ts B00225 : these mutexes are unnecessary because "= 1" is atomar.
pthread_mutex_lock(&d->access_lock); pthread_mutex_lock(&d->access_lock);
*/
d->cancel = 1; d->cancel = 1;
/*
pthread_mutex_unlock(&d->access_lock); pthread_mutex_unlock(&d->access_lock);
*/
} }
/* ts A61007 : defunct because unused */ /* ts A61007 : defunct because unused */
@ -1868,17 +1888,12 @@ int burn_abort_pacifier(void *handle, int patience, int elapsed)
} }
/** Abort any running drive operation and finish libburn. /* ts B00226 : Outsourced backend of burn_abort()
@param patience Maximum number of seconds to wait for drives to finish @param flag bit0= do not call burn_finish()
@param pacifier_func Function to produce appeasing messages. See
burn_abort_pacifier() for an example.
@return 1 ok, all went well
0 had to leave a drive in unclean state
<0 severe error, do no use libburn again
*/ */
int burn_abort(int patience, int burn_abort_5(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed), int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle) void *handle, int elapsed, int flag)
{ {
int ret, i, occup, still_not_done= 1, pacifier_off= 0, first_round= 1; int ret, i, occup, still_not_done= 1, pacifier_off= 0, first_round= 1;
unsigned long wait_grain= 100000; unsigned long wait_grain= 100000;
@ -1888,7 +1903,11 @@ int burn_abort(int patience,
time_t stdio_patience = 3; time_t stdio_patience = 3;
#endif #endif
fprintf(stderr, "libburn_EXPERIMENTAL: burn_abort_5(%d,%d)\n", patience, flag);
current_time = start_time = pacifier_time = time(0); current_time = start_time = pacifier_time = time(0);
start_time -= elapsed;
end_time = start_time + patience; end_time = start_time + patience;
/* >>> ts A71002 : are there any threads at work ? /* >>> ts A71002 : are there any threads at work ?
@ -1935,6 +1954,9 @@ int burn_abort(int patience,
} }
if(occup <= 10) { if(occup <= 10) {
if (drive_array[i].drive_role != 1)
/* occup == -1 comes early */
usleep(1000000);
burn_drive_forget(&(drive_array[i]), 1); burn_drive_forget(&(drive_array[i]), 1);
} else if(occup <= 100) { } else if(occup <= 100) {
if(first_round) if(first_round)
@ -1959,12 +1981,95 @@ int burn_abort(int patience,
pacifier_time = current_time; pacifier_time = current_time;
} }
} }
if (patience > 0) if (!(flag & 1))
burn_finish(); burn_finish();
return(still_not_done == 0); return(still_not_done == 0);
} }
#ifdef NIX
/* <<< did not help. Is on its way out */
/* ts B00226 */
/* Wait for the most delicate drive states to end
*/
int burn_abort_write(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle)
{
int ret, i, still_not_done= 1, pacifier_off= 0;
unsigned long wait_grain= 100000;
time_t start_time, current_time, pacifier_time, end_time;
struct burn_drive *d;
fprintf(stderr, "libburn_EXPERIMENTAL: burn_abort_write\n");
current_time = start_time = pacifier_time = time(0);
end_time = start_time + patience;
while(current_time < end_time || patience <= 0) {
still_not_done = 0;
for(i = 0; i < drivetop + 1; i++) {
d = &(drive_array[i]);
if(d->global_index < 0)
continue;
if(d->busy != BURN_DRIVE_WRITING &&
d->busy != BURN_DRIVE_WRITING_LEADIN &&
d->busy != BURN_DRIVE_WRITING_LEADOUT &&
d->busy != BURN_DRIVE_WRITING_PREGAP &&
d->busy != BURN_DRIVE_CLOSING_TRACK &&
d->busy != BURN_DRIVE_CLOSING_SESSION)
continue;
still_not_done = 1;
}
if(still_not_done == 0 || patience <= 0)
break;
usleep(wait_grain);
current_time = time(0);
if(current_time>pacifier_time) {
if(pacifier_func != NULL && !pacifier_off) {
ret = (*pacifier_func)(handle, patience,
current_time - start_time);
pacifier_off = (ret <= 0);
}
pacifier_time = current_time;
}
}
if (current_time - start_time > patience - 3)
patience = current_time - start_time + 3;
ret = burn_abort_5(patience, pacifier_func, handle,
current_time - start_time, 0);
return ret;
}
#endif /* NIX */
/** Abort any running drive operation and finish libburn.
@param patience Maximum number of seconds to wait for drives to finish
@param pacifier_func Function to produce appeasing messages. See
burn_abort_pacifier() for an example.
@return 1 ok, all went well
0 had to leave a drive in unclean state
<0 severe error, do no use libburn again
*/
int burn_abort(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle)
{
int ret, flg = 0;
if (patience < 0) {
patience = 0;
flg |= 1;
}
ret = burn_abort_5(patience, pacifier_func, handle, 0, flg);
return ret;
}
/* ts A61020 API function */ /* ts A61020 API function */
int burn_drive_get_start_end_lba(struct burn_drive *d, int burn_drive_get_start_end_lba(struct burn_drive *d,
int *start_lba, int *end_lba, int flag) int *start_lba, int *end_lba, int flag)
@ -2698,7 +2803,8 @@ int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
} }
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid) int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid,
pthread_t tid)
{ {
int i; int i;
@ -2710,7 +2816,8 @@ int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid)
*/ */
if (drive_array[i].thread_pid_valid && if (drive_array[i].thread_pid_valid &&
drive_array[i].thread_pid == pid) { drive_array[i].thread_pid == pid &&
pthread_equal(drive_array[i].thread_tid, tid)) {
*d = &(drive_array[i]); *d = &(drive_array[i]);
return 1; return 1;
} }

View File

@ -127,8 +127,9 @@ int burn_disc_get_write_mode_demands(struct burn_disc *disc,
int burn_drive__fd_from_special_adr(char *adr); int burn_drive__fd_from_special_adr(char *adr);
/* ts A70929 : Find the drive which is being worked on by pid */ /* ts A70929 : Find the drive which is being worked on by pid , tid */
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid); int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid,
pthread_t tid);
/* ts A51221 - A80731 : Whitelist inquiry functions */ /* ts A51221 - A80731 : Whitelist inquiry functions */
@ -140,5 +141,20 @@ char *burn_drive_whitelist_item(int idx, int flag);
/* ts A80801 */ /* ts A80801 */
int burn_drive_is_listed(char *path, struct burn_drive **found, int flag); int burn_drive_is_listed(char *path, struct burn_drive **found, int flag);
#ifdef NIX
/* <<< did not help. Is on its way out */
/* ts B00226 */
int burn_abort_write(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle);
#endif /* NIX */
/* ts B00226 : Outsourced backend of burn_abort()
@param elapsed to be subtracted from start time
@param flag bit0= do not shutdown the library
*/
int burn_abort_5(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle, int elapsed, int flag);
#endif /* __DRIVE */ #endif /* __DRIVE */

View File

@ -15,6 +15,7 @@
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <pthread.h>
/* ts A70928 : init.h is for others, not for init .c /* ts A70928 : init.h is for others, not for init .c
#include "init.h" #include "init.h"
@ -80,10 +81,13 @@ static char sg_initialize_msg[1024] = {""};
/* Parameters for builtin abort handler */ /* Parameters for builtin abort handler */
static char abort_message_prefix[81] = {"libburn : "}; static char abort_message_prefix[81] = {"libburn : "};
static pid_t abort_control_pid= 0; static pid_t abort_control_pid= 0;
static pthread_t abort_control_thread;
volatile int burn_global_abort_level= 0; volatile int burn_global_abort_level= 0;
int burn_global_abort_signum= 0; int burn_global_abort_signum= 0;
void *burn_global_signal_handle = NULL; void *burn_global_signal_handle = NULL;
burn_abort_handler_t burn_global_signal_handler = NULL; burn_abort_handler_t burn_global_signal_handler = NULL;
int burn_builtin_signal_action = 0; /* burn_set_signal_handling() */
volatile int burn_builtin_triggered_action = 0; /* burn_is_aborting() */
/* ts A70223 : wether implemented untested profiles are supported */ /* ts A70223 : wether implemented untested profiles are supported */
@ -329,23 +333,75 @@ int burn_sev_to_text(int severity_number, char **severity_name, int flag)
return ret; return ret;
} }
/* ts B00224 */
char *burn_util_thread_id(pid_t pid, pthread_t tid, char text[80])
{
int i, l;
sprintf(text, "[%d,", getpid());
l= strlen(text);
for(i= 0; i < sizeof(pthread_t) && 2 * i < 80 - l - 3; i++)
sprintf(text + l + 2 * i,
"%2.2X", ((unsigned char *) &tid)[i]);
sprintf(text + l + 2 * i, "]");
return text;
}
int burn_builtin_abort_handler(void *handle, int signum, int flag) int burn_builtin_abort_handler(void *handle, int signum, int flag)
{ {
#define Libburn_new_thread_signal_handleR 1 #define Libburn_new_thread_signal_handleR 1
/* /*
#define Libburn_signal_handler_verbouS 1
*/ */
#define Libburn_signal_handler_verbouS 1
int ret; int ret;
struct burn_drive *d; struct burn_drive *d;
#ifdef Libburn_signal_handler_verbouS #ifdef Libburn_signal_handler_verbouS
fprintf(stderr, char text[80];
"libburn_ABORT: pid = %d , abort_control_pid = %d , sig= %d\n",
getpid(), abort_control_pid, signum); fprintf(stderr, "libburn_ABORT: in = %s\n",
burn_util_thread_id(getpid(), pthread_self(), text));
fprintf(stderr, "libburn_ABORT: ctrl = %s\n",
burn_util_thread_id(abort_control_pid, abort_control_thread,
text));
if (burn_global_signal_handler == burn_builtin_abort_handler)
fprintf(stderr, "libburn_ABORT: signal action = %d\n",
burn_builtin_signal_action);
/* >>> find writing drives and report their tid
fprintf(stderr, "libburn_ABORT: wrt = %s\n",
burn_util_thread_id(0, burn_write_thread_id, text));
fprintf(stderr, "libburn_ABORT: sig= %d\n", signum);
*/
#endif #endif
burn_builtin_triggered_action = burn_builtin_signal_action;
burn_global_abort_level = -1;
if (burn_builtin_signal_action > 1) {
Cleanup_set_handlers(NULL, NULL, 2);
if (burn_builtin_signal_action == 4)
return -2;
fprintf(stderr,"%sABORT : Trying to shut down busy drives\n",
abort_message_prefix);
fprintf(stderr,
"%sABORT : Wait the normal burning time before any kill -9\n",
abort_message_prefix);
burn_abort_5(0, burn_abort_pacifier, abort_message_prefix,
0, 1);
libdax_msgs_submit(libdax_messenger, -1, 0x00020177,
LIBDAX_MSGS_SEV_ABORT, LIBDAX_MSGS_PRIO_HIGH,
"Urged drive worker threads to do emergency halt",
0, 0);
return -2;
}
/* ---- old deprecated stuck-in-abort-handler loop ---- */
/* ts A70928: /* ts A70928:
Must be quick. Allowed to coincide with other thread and to share Must be quick. Allowed to coincide with other thread and to share
the increment with that one. It must not decrease, though, and the increment with that one. It must not decrease, though, and
@ -358,7 +414,8 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
#ifdef Libburn_new_thread_signal_handleR #ifdef Libburn_new_thread_signal_handleR
ret = burn_drive_find_by_thread_pid(&d, getpid()); ret = burn_drive_find_by_thread_pid(&d, getpid(),
pthread_self());
if (ret > 0 && d->busy == BURN_DRIVE_WRITING) { if (ret > 0 && d->busy == BURN_DRIVE_WRITING) {
/* This is an active writer thread */ /* This is an active writer thread */
@ -398,13 +455,13 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
} }
burn_global_abort_level = -1; burn_global_abort_level = -1;
Cleanup_set_handlers(NULL, NULL, 2); Cleanup_set_handlers(NULL, NULL, 2);
fprintf(stderr,"%sABORT : Trying to shut down drive and library\n", fprintf(stderr,"%sABORT : Trying to shut down drive and library\n",
abort_message_prefix); abort_message_prefix);
fprintf(stderr, fprintf(stderr,
"%sABORT : Wait the normal burning time before any kill -9\n", "%sABORT : Wait the normal burning time before any kill -9\n",
abort_message_prefix); abort_message_prefix);
close(0); /* somehow stdin as input blocks abort until EOF */ close(0); /* somehow stdin as input blocks abort until EOF */
burn_abort(4440, burn_abort_pacifier, abort_message_prefix); burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
fprintf(stderr, fprintf(stderr,
@ -414,6 +471,8 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
return(1); return(1);
} }
/* ts A61002 : API */
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler, void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
int mode) int mode)
{ {
@ -436,12 +495,56 @@ void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
sizeof(abort_message_prefix)-1); sizeof(abort_message_prefix)-1);
abort_message_prefix[sizeof(abort_message_prefix)-1] = 0; abort_message_prefix[sizeof(abort_message_prefix)-1] = 0;
abort_control_pid = getpid(); abort_control_pid = getpid();
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler, mode|4); abort_control_thread = pthread_self();
burn_builtin_signal_action = (mode >> 4) & 15;
if((mode & 11) != 0)
burn_builtin_signal_action = 0;
if(burn_builtin_signal_action > 1)
burn_builtin_triggered_action = 0;
if(burn_builtin_signal_action == 0)
burn_builtin_signal_action = 1;
fprintf(stderr, "libburn_EXPERIMENTAL: mode = %d , burn_builtin_signal_action = %d\n",
mode, burn_builtin_signal_action);
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler,
(mode & 15) | 4);
burn_global_signal_handle = handle; burn_global_signal_handle = handle;
burn_global_signal_handler = handler; burn_global_signal_handler = handler;
} }
/* ts B00304 : API */
int burn_is_aborting(int flag)
{
return burn_builtin_triggered_action;
}
/* ts B00225 */
/* @return 0= no abort action 2 pending , 1= not control thread
*/
int burn_init_catch_on_abort(int flag)
{
if (burn_builtin_triggered_action != 2)
return 0;
if (abort_control_pid != getpid() ||
abort_control_thread != pthread_self())
return 1;
#ifdef NIX
burn_abort_write(4440, burn_abort_pacifier, abort_message_prefix);
#else
burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
#endif
fprintf(stderr,
"\n%sABORT : Program done. Even if you do not see a shell prompt.\n\n",
abort_message_prefix);
exit(1);
}
/* ts A70223 : API */ /* ts A70223 : API */
void burn_allow_untested_profiles(int yes) void burn_allow_untested_profiles(int yes)
{ {

View File

@ -17,5 +17,15 @@ extern int burn_global_abort_signum;
extern void *burn_global_signal_handle; extern void *burn_global_signal_handle;
extern burn_abort_handler_t burn_global_signal_handler; extern burn_abort_handler_t burn_global_signal_handler;
extern int burn_builtin_signal_action; /* burn_set_signal_handling() */
extern volatile int burn_builtin_triggered_action; /* burn_is_aborting() */
/* ts B00225 */
/* @return 0= no abort pending , 1= not control thread ,
-1= surprisingly burn_abort returned
*/
int burn_init_catch_on_abort(int flag);
#endif /* BURN__INIT_H */ #endif /* BURN__INIT_H */

View File

@ -736,14 +736,19 @@ void burn_finish(void);
/* ts A61002 */ /* ts A61002 */
/** Abort any running drive operation and finally call burn_finish(). /** Abort any running drive operation and eventually call burn_finish().
You MUST calm down the busy drive if an aborting event occurs during a
You MUST shut down the busy drives if an aborting event occurs during a
burn run. For that you may call this function either from your own signal burn run. For that you may call this function either from your own signal
handling code or indirectly by activating the builtin signal handling: handling code or indirectly by activating the built-in signal handling:
burn_set_signal_handling("my_app_name : ", NULL, 0); burn_set_signal_handling("my_app_name : ", NULL, 0);
Else you may eventually call burn_drive_cancel() on the active drive and Else you may eventually call burn_drive_cancel() on the active drives and
wait for it to assume state BURN_DRIVE_IDLE. wait for them to assume state BURN_DRIVE_IDLE.
@param patience Maximum number of seconds to wait for drives to finish @param patience Maximum number of seconds to wait for drives to
finish.
@since 0.7.8 :
If this is -1, then only the cancel operations will
be performed and no burn_finish() will happen.
@param pacifier_func If not NULL: a function to produce appeasing messages. @param pacifier_func If not NULL: a function to produce appeasing messages.
See burn_abort_pacifier() for an example. See burn_abort_pacifier() for an example.
@param handle Opaque handle to be used with pacifier_func @param handle Opaque handle to be used with pacifier_func
@ -2784,30 +2789,78 @@ int burn_set_messenger(void *messenger);
/* ts A61002 */ /* ts A61002 */
/* @since 0.2.6 */ /* @since 0.2.6 */
/** The prototype of a handler function suitable for burn_set_abort_handling(). /** The prototype of a handler function suitable for burn_set_signal_handling()
Such a function has to return -2 if it does not want the process to Such a function has to return -2 if it does not want the process to
exit with value 1. exit with value 1.
*/ */
typedef int (*burn_abort_handler_t)(void *handle, int signum, int flag); typedef int (*burn_abort_handler_t)(void *handle, int signum, int flag);
/** Control builtin signal handling. See also burn_abort(). /** Control built-in signal handling. Either by setting an own handler or
by activating the built-in signal handler.
A function parameter handle of NULL activates the built-in abort handler.
Depending on mode it may cancel all drive operations, wait for all drives
to become idle, exit(1). It may also prepare function
burn_drive_get_status() for waiting and performing exit(1).
If text is not NULL then it is used as prefix for pacifier messages of
burn_abort_pacifier().
Before version 0.7.8 only action 0 was available. I.e. the built-in handler
waited for the drives to become idle and then performed exit(1) directly.
But FreeBSD 8.0 sometimes pauses the other threads until the signal handler
returns.
The new actions try to avoid this deadlock. It is advised to use action 3
burn_set_signal_handling(text, NULL, 48);
and call burn_is_aborting(0) frequently. If it replies 1, then call
burn_abort() and exit(1).
@param handle Opaque handle eventually pointing to an application @param handle Opaque handle eventually pointing to an application
provided memory object provided memory object
@param handler A function to be called on signals. It will get handle as @param handler A function to be called on signals. It will get handle as
argument. It should finally call burn_abort(). See there. argument. flag will be 0.
@param mode : 0 call handler(handle, signum, 0) on nearly all signals It should finally call burn_abort(). See there.
1 enable system default reaction on all signals @param mode : bit0 - bit3:
2 try to ignore nearly all signals Receiving signals:
0 Call handler(handle, signum, 0) on nearly all signals
1 Enable system default reaction on all signals
2 Try to ignore nearly all signals
10 like mode 2 but handle SIGABRT like with mode 0 10 like mode 2 but handle SIGABRT like with mode 0
Arguments (text, NULL, 0) activate the builtin abort handler. It will bit4 - bit7: With handler == NULL :
eventually call burn_abort() and then perform exit(1). If text is not NULL Action of built-in handler. "control thread" is the one
then it is used as prefix for pacifier messages of burn_abort_pacifier(). which called burn_set_signal_handling().
All actions activate receive mode 2 to ignore further
signals.
0 Same as 1 (for pre-0.7.8 backward compatibility)
@since 0.7.8
1 Catch the control thread in abort handler, call
burn_abort(>0) and finally exit(1).
Does not always work with FreeBSD.
2 Call burn_abort(-1) and return from handler. When the
control thread calls burn_drive_get_status(), then do
burn_abort(>0) instead, and finally exit(1).
Does not always work with FreeBSD.
3 Call burn_abort(-1), return from handler. It is duty of
the application to detect a pending abort condition
by calling burn_is_aborting() and to wait for all
drives to become idle. E.g. by calling burn_abort(>0).
4 Like 3, but without calling burn_abort(-1). Only the
indicator of burn_is_aborting() gets set.
@since 0.2.6 @since 0.2.6
*/ */
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler, void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
int mode); int mode);
/* ts B00304 */
/* Inquire whether the built-in abort handler was triggered by a signal.
This has to be done to detect pending abort handling if signal handling
was set to the built-in handler and action was set to 2 or 3.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 0 = no abort was triggered
>0 = action that was triggered (action 0 is reported as 1)
@since 0.7.8
*/
int burn_is_aborting(int flag);
/* ts A70811 */ /* ts A70811 */
/** Write data in random access mode. /** Write data in random access mode.
The drive must be grabbed successfully before calling this function which The drive must be grabbed successfully before calling this function which
@ -2955,5 +3008,11 @@ BURN_END_DECLS
#define Libburn_dummy_probe_write_modeS 1 #define Libburn_dummy_probe_write_modeS 1
/* ts B00225 */
/* Leave abort handler quickly and catch control thread in
burn_drive_get_status().
*/
#define Libburn_signal_handler_return_2 1
#endif /*LIBBURN_H*/ #endif /*LIBBURN_H*/

View File

@ -12,6 +12,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <sys/time.h> #include <sys/time.h>
#include <pthread.h>
/* Only this single source module is entitled to do this */ /* Only this single source module is entitled to do this */
#define LIBDAX_MSGS_H_INTERNAL 1 #define LIBDAX_MSGS_H_INTERNAL 1

View File

@ -554,6 +554,8 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020174 (SORRY,HIGH) = Fifo alignment does not allow desired read size 0x00020174 (SORRY,HIGH) = Fifo alignment does not allow desired read size
0x00020175 (FATAL,HIGH) = Supporting library is too old 0x00020175 (FATAL,HIGH) = Supporting library is too old
0x00020176 (NOTE,HIGH) = Stream recording disabled because of small OS buffer 0x00020176 (NOTE,HIGH) = Stream recording disabled because of small OS buffer
0x00020177 (ABORT,HIGH) = Urged drive worker threads to do emergency halt
0x00020178 (DEBUG,HIGH) = Write thread ended
libdax_audioxtr: libdax_audioxtr:

View File

@ -31,7 +31,7 @@ extern struct libdax_msgs *libdax_messenger;
#ifdef Libburn_log_in_and_out_streaM #ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */ /* ts A61031 */
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@ -102,7 +102,7 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
int valid, shortage, curr, i, tr; int valid, shortage, curr, i, tr;
#ifdef Libburn_log_in_and_out_streaM #ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */ /* ts A61031 */
static int tee_fd= -1; static int tee_fd= -1;
if(tee_fd==-1) if(tee_fd==-1)
tee_fd= open("/tmp/libburn_sg_readin", tee_fd= open("/tmp/libburn_sg_readin",
@ -148,7 +148,7 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
track->sourcecount += valid; track->sourcecount += valid;
#ifdef Libburn_log_in_and_out_streaM #ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */ /* ts A61031 */
if(tee_fd!=-1 && valid>0) { if(tee_fd!=-1 && valid>0) {
write(tee_fd, data + curr, valid); write(tee_fd, data + curr, valid);
} }
@ -678,7 +678,7 @@ int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub)
unsigned char *data; unsigned char *data;
data = get_sector(o, t, t->mode); data = get_sector(o, t, t->mode);
if (!data) if (data == NULL)
return 0; return 0;
/* ts A61010 */ /* ts A61010 */
if (convert_data(o, t, t->mode, data) <= 0) if (convert_data(o, t, t->mode, data) <= 0)

View File

@ -312,6 +312,8 @@ struct burn_drive
/* ts A70929 */ /* ts A70929 */
pid_t thread_pid; pid_t thread_pid;
int thread_pid_valid; int thread_pid_valid;
/* ts B00225 */
pthread_t thread_tid;
/* transport functions */ /* transport functions */

View File

@ -1312,7 +1312,7 @@ static int transact_dvd_chunk(struct burn_write_opts *opts,
unsigned char *data = out->data; unsigned char *data = out->data;
#ifdef Libburn_log_in_and_out_streaM #ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */ /* ts A61031 */
static int tee_fd= -1; static int tee_fd= -1;
if(tee_fd==-1) if(tee_fd==-1)
tee_fd= open("/tmp/libburn_sg_readin", tee_fd= open("/tmp/libburn_sg_readin",
@ -2002,7 +2002,7 @@ ex:;
burn_drive_mark_unready(d); burn_drive_mark_unready(d);
burn_drive_inquire_media(d); burn_drive_inquire_media(d);
d->busy = BURN_DRIVE_IDLE; /* <<< d->busy = BURN_DRIVE_IDLE; */
return ret; return ret;
early_failure:; early_failure:;
return 0; return 0;
@ -2330,7 +2330,7 @@ ex:;
/* update media state records */ /* update media state records */
burn_drive_mark_unready(d); burn_drive_mark_unready(d);
d->busy = BURN_DRIVE_IDLE; /* <<< d->busy = BURN_DRIVE_IDLE; */
return ret; return ret;
} }
@ -2567,7 +2567,7 @@ return crap. so we send the command, then ignore the result.
burn_drive_inquire_media(d); burn_drive_inquire_media(d);
burn_print(1, "done\n"); burn_print(1, "done\n");
d->busy = BURN_DRIVE_IDLE; /* <<< d->busy = BURN_DRIVE_IDLE; */
/* ts A61012 : This return was traditionally missing. I suspect this /* ts A61012 : This return was traditionally missing. I suspect this
to have caused Cdrskin_eject() failures */ to have caused Cdrskin_eject() failures */
@ -2582,7 +2582,7 @@ fail_wo_sync:;
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Burn run failed", 0, 0); "Burn run failed", 0, 0);
d->cancel = 1; d->cancel = 1;
d->busy = BURN_DRIVE_IDLE; /* <<< d->busy = BURN_DRIVE_IDLE; */
ex:; ex:;
d->do_stream_recording = 0; d->do_stream_recording = 0;
if (d->buffer != NULL) if (d->buffer != NULL)