diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 80462ef..079757a 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2007.09.27.093129" +#define Cdrskin_timestamP "2007.09.29.185007" diff --git a/libburn/async.c b/libburn/async.c index 6f05d42..f2c9413 100644 --- a/libburn/async.c +++ b/libburn/async.c @@ -338,7 +338,13 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag) static void *write_disc_worker_func(struct w_list *w) { + struct burn_drive *d = w->u.write.drive; + + d->thread_pid = getpid(); + d->thread_pid_valid= 1; burn_disc_write_sync(w->u.write.opts, w->u.write.disc); + d->thread_pid_valid= 0; + d->thread_pid = 0; /* the options are refcounted, free out ref count which we added below */ diff --git a/libburn/drive.c b/libburn/drive.c index dfe83ee..eba810c 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -18,6 +18,7 @@ #include #include #include "libburn.h" +#include "init.h" #include "drive.h" #include "transport.h" #include "debug.h" @@ -163,8 +164,18 @@ int burn_drive_is_occupied(struct burn_drive *d) if(d->busy == BURN_DRIVE_READING_SYNC || d->busy == BURN_DRIVE_WRITING_SYNC) return 2; - if(d->busy == BURN_DRIVE_READING || d->busy == BURN_DRIVE_WRITING) + if(d->busy == BURN_DRIVE_WRITING) { + + /* ts A70928 */ + /* >>> how do i learn whether the writer thread is still + alive ? */; + /* >>> what to do if writer is dead ? + At least sync disc ?*/; + + } + if(d->busy == BURN_DRIVE_READING) { return 50; + } return 1000; } @@ -317,6 +328,8 @@ struct burn_drive *burn_drive_register(struct burn_drive *d) d->rlba = 0; d->cancel = 0; d->busy = BURN_DRIVE_IDLE; + d->thread_pid = 0; + d->thread_pid_valid = 0; d->toc_entries = 0; d->toc_entry = NULL; d->disc = NULL; @@ -717,6 +730,19 @@ int burn_disc_erasable(struct burn_drive *d) enum burn_drive_status burn_drive_get_status(struct burn_drive *d, struct burn_progress *p) { + /* ts A70928 : inform control thread of signal in sub-threads */ + if (burn_global_abort_level > 0) + burn_global_abort_level++; + if (burn_global_abort_level > 5) { + if (burn_global_signal_handler == NULL) + kill(getpid(), burn_global_abort_signum); + else + (*burn_global_signal_handler) + (burn_global_signal_handle, + burn_global_abort_signum, 0); + burn_global_abort_level = -1; + } + if (p != NULL) { memcpy(p, &(d->progress), sizeof(struct burn_progress)); /* TODO: add mutex */ @@ -2376,3 +2402,17 @@ 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 i; + + for (i = 0; i < drivetop + 1; i++) + if (drive_array[i].thread_pid_valid && + drive_array[i].thread_pid == pid) { + *d = &(drive_array[i]); + return 1; + } + return 0; +} + + diff --git a/libburn/drive.h b/libburn/drive.h index 640960f..8441293 100644 --- a/libburn/drive.h +++ b/libburn/drive.h @@ -121,4 +121,8 @@ int burn_disc_get_write_mode_demands(struct burn_disc *disc, int burn_drive__fd_from_special_adr(char *adr); +/* ts A70929 : Find the drive which is being worked on by pid */ +int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid); + + #endif /* __DRIVE */ diff --git a/libburn/init.c b/libburn/init.c index 2f9050e..9aa98b0 100644 --- a/libburn/init.c +++ b/libburn/init.c @@ -10,8 +10,11 @@ #include #include - +/* ts A70928 : init.h is for others, not for init .c #include "init.h" +*/ + + #include "sg.h" #include "error.h" #include "libburn.h" @@ -56,7 +59,6 @@ int burn_sg_open_o_nonblock = 1; to unconditional abort of the process */ int burn_sg_open_abort_busy = 0; - /* ts A61002 */ #include "cleanup.h" @@ -64,6 +66,10 @@ int burn_sg_open_abort_busy = 0; /* Parameters for builtin abort handler */ static char abort_message_prefix[81] = {"libburn : "}; static pid_t abort_control_pid= 0; +volatile int burn_global_abort_level= 0; +int burn_global_abort_signum= 0; +void *burn_global_signal_handle = NULL; +burn_abort_handler_t burn_global_signal_handler = NULL; /* ts A70223 : wether implemented untested profiles are supported */ @@ -263,38 +269,57 @@ int burn_msgs_submit(int error_code, char msg_text[], int os_errno, int burn_builtin_abort_handler(void *handle, int signum, int flag) { +#define Libburn_new_thread_signal_handleR 1 + int ret; + struct burn_drive *d; + + /* + fprintf(stderr, "libburn_ABORT: pid = %d , abort_control_pid = %d\n", + getpid(), abort_control_pid); + */ + + /* ts A70928: + Must be quick. Allowed to coincide with other thread and to share + the increment with that one. It must not decrease, though, and + yield at least 1 if any thread calls this function. + */ + burn_global_abort_level++; + burn_global_abort_signum= signum; + if(getpid() != abort_control_pid) { -#ifdef Not_yeT - pthread_t thread_id; +#ifdef Libburn_new_thread_signal_handleR - /* >>> need better handling of self-induced SIGs - like SIGSEGV or SIGFPE. - Like bonking the control thread if it did not show up - after a short while. - */ + ret = burn_drive_find_by_thread_pid(&d, getpid()); + if (ret > 0 && d->busy == BURN_DRIVE_WRITING) { + /* This is an active writer thread */ +/* + fprintf(stderr, "libburn_ABORT: pid %d found drive busy with writing, (level= %d)\n", (int) getpid(), burn_global_abort_level); +*/ - /* >>> if this is a non-fatal signal : return -2 */ + d->sync_cache(d); - thread_id = pthread_self(); - /* >>> find thread_id in worker list of async.c */ - /* >>> if owning a drive : mark idle and canceled - (can't do anything more) */ + /* >>> perform a more qualified end of burn process */; - usleep(1000000); /* calm down */ + d->busy = BURN_DRIVE_IDLE; - /* forward signal to control thread */ - if (abort_control_pid>1) - kill(abort_control_pid, signum); - - /* >>> ??? end thread */; + if (burn_global_abort_level > 0) { + /* control process did not show up yet */ +/* + fprintf(stderr, "libburn_ABORT: pid %d sending signum %d to pid %d\n", (int) getpid(), (int) signum, (int) abort_control_pid); +*/ + kill(abort_control_pid, signum); + } + return -2; + } #else usleep(1000000); /* calm down */ return -2; -#endif /* ! Not_yeT */ +#endif /* ! Libburn_new_thread_signal_handleR */ } + burn_global_abort_level = -1; Cleanup_set_handlers(NULL, NULL, 2); fprintf(stderr,"%sABORT : Trying to shut down drive and library\n", abort_message_prefix); @@ -302,10 +327,13 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag) "%sABORT : Wait the normal burning time before any kill -9\n", abort_message_prefix); close(0); /* somehow stdin as input blocks abort until EOF */ + burn_abort(4440, burn_abort_pacifier, abort_message_prefix); + fprintf(stderr, "\n%sABORT : Program done. Even if you do not see a shell prompt.\n\n", abort_message_prefix); + burn_global_abort_level = -2; return(1); } @@ -326,6 +354,8 @@ void burn_set_signal_handling(void *handle, burn_abort_handler_t handler, abort_message_prefix[sizeof(abort_message_prefix)-1] = 0; abort_control_pid = getpid(); Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler, mode|4); + burn_global_signal_handle = handle; + burn_global_signal_handler = handler; } diff --git a/libburn/init.h b/libburn/init.h index c3e9b9a..ba2fb4f 100644 --- a/libburn/init.h +++ b/libburn/init.h @@ -5,4 +5,17 @@ extern int burn_running; +/** Indicator for burn_drive_get_status() wether a signal hit parts of the + thread team. + 0= all works well , + 1 to 5 = waiting for eventual signal on control thread + > 5 = do abort now + -1 = control thread has been informed +*/ +extern volatile int burn_global_abort_level; +extern int burn_global_abort_signum; +extern void *burn_global_signal_handle; +extern burn_abort_handler_t burn_global_signal_handler; + + #endif /* BURN__INIT_H */ diff --git a/libburn/transport.h b/libburn/transport.h index 5ae08d4..a3e57b3 100644 --- a/libburn/transport.h +++ b/libburn/transport.h @@ -251,6 +251,12 @@ struct burn_drive volatile int cancel; volatile enum burn_drive_status busy; + + /* ts A70929 */ + pid_t thread_pid; + int thread_pid_valid; + + /* transport functions */ int (*grab) (struct burn_drive *); int (*release) (struct burn_drive *);