Trying to catch signals from within the writer thread

This commit is contained in:
Thomas Schmitt 2007-09-29 18:50:19 +00:00
parent 3dda4b92b9
commit 5d93e04b28
7 changed files with 122 additions and 23 deletions

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2007.09.27.093129"
#define Cdrskin_timestamP "2007.09.29.185007"

View File

@ -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
*/

View File

@ -18,6 +18,7 @@
#include <pthread.h>
#include <errno.h>
#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;
}

View File

@ -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 */

View File

@ -10,8 +10,11 @@
#include <string.h>
#include <stdlib.h>
/* 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;
}

View File

@ -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 */

View File

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