Commit 2fa6c9ce authored by Sam Hocevar's avatar Sam Hocevar

* ./src/misc/cpu.c: libvlc now plays nice with SIGILL and restores the

    signal handler to its previous value after use.
  * ./src/libvlc.c: moved signal handling to vlc.c.
parent 9c669a9f
......@@ -2,7 +2,7 @@
* vlc.h: global header for vlc
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc.h,v 1.8 2002/08/14 17:06:53 sam Exp $
* $Id: vlc.h,v 1.9 2002/08/19 11:13:44 sam Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -114,6 +114,7 @@ vlc_status_t vlc_status ( void );
vlc_error_t vlc_create ( void );
vlc_error_t vlc_init ( int, char *[] );
vlc_error_t vlc_run ( void );
vlc_error_t vlc_die ( void );
vlc_error_t vlc_stop ( void );
vlc_error_t vlc_end ( void );
vlc_error_t vlc_destroy ( void );
......@@ -129,6 +130,7 @@ vlc_status_t vlc_status_r ( vlc_t * );
vlc_t * vlc_create_r ( void );
vlc_error_t vlc_init_r ( vlc_t *, int, char *[] );
vlc_error_t vlc_run_r ( vlc_t * );
vlc_error_t vlc_die_r ( vlc_t * );
vlc_error_t vlc_stop_r ( vlc_t * );
vlc_error_t vlc_end_r ( vlc_t * );
vlc_error_t vlc_destroy_r ( vlc_t * );
......
......@@ -2,7 +2,7 @@
* libvlc.c: main libvlc source
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
* $Id: libvlc.c,v 1.27 2002/08/18 13:49:20 sam Exp $
* $Id: libvlc.c,v 1.28 2002/08/19 11:13:45 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -37,7 +37,6 @@
#include <stdio.h> /* sprintf() */
#include <string.h> /* strerror() */
#include <stdlib.h> /* free() */
#include <signal.h> /* SIGHUP, SIGINT, SIGKILL */
#include <vlc/vlc.h>
......@@ -102,11 +101,6 @@ static void Usage ( vlc_t *, const char *psz_module_name );
static void ListModules ( vlc_t * );
static void Version ( void );
#ifndef WIN32
static void InitSignalHandler ( void );
static void FatalSignalHandler ( int i_signal );
#endif
#ifdef WIN32
static void ShowConsole ( void );
#endif
......@@ -115,12 +109,45 @@ static void ShowConsole ( void );
* vlc_create: allocate a vlc_t structure, and initialize libvlc if needed.
*****************************************************************************
* This function allocates a vlc_t structure and returns NULL in case of
* failure. Also, the thread system and the signal handlers are initialized.
* failure. Also, the thread system is initialized.
*****************************************************************************/
vlc_error_t vlc_create( void )
{
vlc_t * p_vlc = vlc_create_r();
return p_vlc ? VLC_SUCCESS : VLC_EGENERIC;
vlc_t * p_vlc;
vlc_bool_t b_failed = VLC_FALSE;
/* This gives us a rather good protection against concurrent calls, but
* an additional check will be necessary for complete thread safety. */
if( i_vlc )
{
return VLC_EGENERIC;
}
p_vlc = vlc_create_r();
if( p_vlc == NULL )
{
return VLC_EGENERIC;
}
/* We have created an object, which ensures us that p_global_lock has
* been properly initialized. We can now atomically check that we are
* the only p_vlc object. */
vlc_mutex_lock( p_vlc->p_global_lock );
if( i_vlc != 1 )
{
b_failed = VLC_TRUE;
}
vlc_mutex_unlock( p_vlc->p_global_lock );
/* There can be only one */
if( b_failed )
{
vlc_destroy_r( p_vlc );
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
vlc_t * vlc_create_r( void )
......@@ -149,11 +176,6 @@ vlc_t * vlc_create_r( void )
vlc_mutex_init( p_vlc, &p_vlc->config_lock );
vlc_mutex_init( p_vlc, &p_vlc->structure_lock );
/* Set signal handling policy for all threads */
#ifndef WIN32
InitSignalHandler( );
#endif
/* Store our newly allocated structure in the global list */
vlc_mutex_lock( p_vlc->p_global_lock );
pp_vlc = realloc( pp_vlc, (i_vlc+1) * sizeof( vlc_t * ) );
......@@ -180,7 +202,7 @@ vlc_t * vlc_create_r( void )
*****************************************************************************/
vlc_error_t vlc_init( int i_argc, char *ppsz_argv[] )
{
return vlc_init_r( ( i_vlc == 1 ) ? *pp_vlc : NULL, i_argc, ppsz_argv );
return vlc_init_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL, i_argc, ppsz_argv );
}
vlc_error_t vlc_init_r( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
......@@ -197,8 +219,6 @@ vlc_error_t vlc_init_r( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
return VLC_ESTATUS;
}
fprintf( stderr, COPYRIGHT_MESSAGE "\n" );
/* Guess what CPU we have */
p_vlc->i_cpu = CPUCapabilities( p_vlc );
......@@ -511,7 +531,7 @@ vlc_error_t vlc_init_r( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
*****************************************************************************/
vlc_error_t vlc_run( void )
{
return vlc_run_r( ( i_vlc == 1 ) ? *pp_vlc : NULL );
return vlc_run_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
}
vlc_error_t vlc_run_r( vlc_t *p_vlc )
......@@ -539,7 +559,7 @@ vlc_error_t vlc_run_r( vlc_t *p_vlc )
*****************************************************************************/
vlc_error_t vlc_add_intf( const char *psz_module, vlc_bool_t b_block )
{
return vlc_add_intf_r( ( i_vlc == 1 ) ? *pp_vlc : NULL,
return vlc_add_intf_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL,
psz_module, b_block );
}
......@@ -602,7 +622,7 @@ vlc_error_t vlc_add_intf_r( vlc_t *p_vlc, const char *psz_module,
*****************************************************************************/
vlc_error_t vlc_stop( void )
{
return vlc_stop_r( ( i_vlc == 1 ) ? *pp_vlc : NULL );
return vlc_stop_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
}
vlc_error_t vlc_stop_r( vlc_t *p_vlc )
......@@ -679,7 +699,7 @@ vlc_error_t vlc_stop_r( vlc_t *p_vlc )
*****************************************************************************/
vlc_error_t vlc_end( void )
{
return vlc_end_r( ( i_vlc == 1 ) ? *pp_vlc : NULL );
return vlc_end_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
}
vlc_error_t vlc_end_r( vlc_t *p_vlc )
......@@ -737,7 +757,7 @@ vlc_error_t vlc_end_r( vlc_t *p_vlc )
*****************************************************************************/
vlc_error_t vlc_destroy( void )
{
return vlc_destroy_r( ( i_vlc == 1 ) ? *pp_vlc : NULL );
return vlc_destroy_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
}
vlc_error_t vlc_destroy_r( vlc_t *p_vlc )
......@@ -802,9 +822,38 @@ vlc_error_t vlc_destroy_r( vlc_t *p_vlc )
return VLC_SUCCESS;
}
/*****************************************************************************
* vlc_die: ask vlc to die.
*****************************************************************************
* This function sets p_vlc->b_die to VLC_TRUE, but does not do any other
* task. It is your duty to call vlc_end and vlc_destroy afterwards.
*****************************************************************************/
vlc_error_t vlc_die( void )
{
return vlc_die_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
}
vlc_error_t vlc_die_r( vlc_t *p_vlc )
{
if( !p_vlc )
{
fprintf( stderr, "error: invalid status (!EXIST)\n" );
return VLC_ESTATUS;
}
p_vlc->b_die = VLC_TRUE;
return VLC_SUCCESS;
}
/*****************************************************************************
* vlc_status: return the current vlc status.
*****************************************************************************
* This function returns the current value of p_vlc->i_status.
*****************************************************************************/
vlc_status_t vlc_status( void )
{
return vlc_status_r( ( i_vlc == 1 ) ? *pp_vlc : NULL );
return vlc_status_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL );
}
vlc_status_t vlc_status_r( vlc_t *p_vlc )
......@@ -817,9 +866,15 @@ vlc_status_t vlc_status_r( vlc_t *p_vlc )
return p_vlc->i_status;
}
/*****************************************************************************
* vlc_add_target: adds a target for playing.
*****************************************************************************
* This function adds psz_target to the current playlist. If a playlist does
* not exist, it will create one.
*****************************************************************************/
vlc_error_t vlc_add_target( const char *psz_target, int i_mode, int i_pos )
{
return vlc_add_target_r( ( i_vlc == 1 ) ? *pp_vlc : NULL,
return vlc_add_target_r( ( i_vlc == 1 ) ? pp_vlc[0] : NULL,
psz_target, i_mode, i_pos );
}
......@@ -1177,69 +1232,3 @@ static void ShowConsole( void )
}
#endif
#ifndef WIN32
/*****************************************************************************
* InitSignalHandler: system signal handler initialization
*****************************************************************************
* Set the signal handlers. SIGTERM is not intercepted, because we need at
* at least a method to kill the program when all other methods failed, and
* when we don't want to use SIGKILL.
*****************************************************************************/
static void InitSignalHandler( void )
{
/* Termination signals */
signal( SIGINT, FatalSignalHandler );
signal( SIGHUP, FatalSignalHandler );
signal( SIGQUIT, FatalSignalHandler );
/* Other signals */
signal( SIGALRM, SIG_IGN );
signal( SIGPIPE, SIG_IGN );
}
/*****************************************************************************
* FatalSignalHandler: system signal handler
*****************************************************************************
* This function is called when a fatal signal is received by the program.
* It tries to end the program in a clean way.
*****************************************************************************/
static void FatalSignalHandler( int i_signal )
{
static mtime_t abort_time = 0;
static volatile vlc_bool_t b_die = VLC_FALSE;
int i_index;
/* Once a signal has been trapped, the termination sequence will be
* armed and following signals will be ignored to avoid sending messages
* to an interface having been destroyed */
if( !b_die )
{
b_die = VLC_TRUE;
abort_time = mdate();
fprintf( stderr, "signal %d received, terminating libvlc - do it "
"again in case your process gets stuck\n", i_signal );
/* Try to terminate everything - this is done by requesting the end of
* all the p_vlc structures */
for( i_index = 0 ; i_index < i_vlc ; i_index++ )
{
/* Acknowledge the signal received */
pp_vlc[ i_index ]->b_die = VLC_TRUE;
}
}
else if( mdate() > abort_time + 1000000 )
{
/* If user asks again 1 second later, die badly */
signal( SIGINT, SIG_IGN );
signal( SIGHUP, SIG_IGN );
signal( SIGQUIT, SIG_IGN );
fprintf( stderr, "user insisted too much, dying badly\n" );
exit( 1 );
}
}
#endif
......@@ -2,7 +2,7 @@
* cpu.c: CPU detection code
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
* $Id: cpu.c,v 1.4 2002/06/07 14:30:41 sam Exp $
* $Id: cpu.c,v 1.5 2002/08/19 11:13:45 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Christophe Massiot <massiot@via.ecp.fr>
......@@ -43,7 +43,8 @@
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static void IllegalSignalHandler( int i_signal );
static void SigHandler ( int );
static u32 Capabilities ( vlc_object_t * );
/*****************************************************************************
* Global variables - they're needed for signal handling
......@@ -55,11 +56,27 @@ static char *psz_capability;
#endif
/*****************************************************************************
* CPUCapabilities: list the processors MMX support and other capabilities
* CPUCapabilities: get the CPU capabilities
*****************************************************************************
* This function is called to list extensions the CPU may have.
* This function is a wrapper around Capabilities().
*****************************************************************************/
u32 __CPUCapabilities( vlc_object_t *p_this )
{
u32 i_capabilities;
vlc_mutex_lock( p_this->p_vlc->p_global_lock );
i_capabilities = Capabilities( p_this );
vlc_mutex_unlock( p_this->p_vlc->p_global_lock );
return i_capabilities;
}
/*****************************************************************************
* Capabilities: list the processors MMX support and other capabilities
*****************************************************************************
* This function is called to list extensions the CPU may have.
*****************************************************************************/
static u32 Capabilities( vlc_object_t *p_this )
{
volatile u32 i_capabilities = CPU_CAPABILITY_NONE;
......@@ -112,12 +129,12 @@ u32 __CPUCapabilities( vlc_object_t *p_this )
: "a" ( a ) \
: "cc" );
i_capabilities |= CPU_CAPABILITY_FPU;
# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
signal( SIGILL, IllegalSignalHandler );
sighandler_t pf_sigill = signal( SIGILL, SigHandler );
# endif
i_capabilities |= CPU_CAPABILITY_FPU;
/* test for a 486 CPU */
asm volatile ( "pushl %%ebx\n\t"
"pushfl\n\t"
......@@ -138,7 +155,7 @@ u32 __CPUCapabilities( vlc_object_t *p_this )
if( i_eax == i_ebx )
{
# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
signal( SIGILL, NULL );
signal( SIGILL, pf_sigill );
# endif
return i_capabilities;
}
......@@ -151,7 +168,7 @@ u32 __CPUCapabilities( vlc_object_t *p_this )
if( !i_eax )
{
# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
signal( SIGILL, NULL );
signal( SIGILL, pf_sigill );
# endif
return i_capabilities;
}
......@@ -169,7 +186,7 @@ u32 __CPUCapabilities( vlc_object_t *p_this )
if( ! (i_edx & 0x00800000) )
{
# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
signal( SIGILL, NULL );
signal( SIGILL, pf_sigill );
# endif
return i_capabilities;
}
......@@ -185,13 +202,11 @@ u32 __CPUCapabilities( vlc_object_t *p_this )
psz_capability = "SSE";
i_illegal = 0;
vlc_mutex_lock( p_this->p_vlc->p_global_lock );
if( setjmp( env ) == 0 )
{
/* Test a SSE instruction */
__asm__ __volatile__ ( "xorps %%xmm0,%%xmm0\n" : : );
}
vlc_mutex_unlock( p_this->p_vlc->p_global_lock );
if( i_illegal == 0 )
{
......@@ -206,7 +221,7 @@ u32 __CPUCapabilities( vlc_object_t *p_this )
if( i_eax < 0x80000001 )
{
# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
signal( SIGILL, NULL );
signal( SIGILL, pf_sigill );
# endif
return i_capabilities;
}
......@@ -220,13 +235,11 @@ u32 __CPUCapabilities( vlc_object_t *p_this )
psz_capability = "3D Now!";
i_illegal = 0;
vlc_mutex_lock( p_this->p_vlc->p_global_lock );
if( setjmp( env ) == 0 )
{
/* Test a 3D Now! instruction */
__asm__ __volatile__ ( "pfadd %%mm0,%%mm0\n" "femms\n" : : );
}
vlc_mutex_unlock( p_this->p_vlc->p_global_lock );
if( i_illegal == 0 )
{
......@@ -241,20 +254,19 @@ u32 __CPUCapabilities( vlc_object_t *p_this )
}
# if defined( CAN_COMPILE_SSE ) || defined ( CAN_COMPILE_3DNOW )
signal( SIGILL, NULL );
signal( SIGILL, pf_sigill );
# endif
return i_capabilities;
#elif defined( __powerpc__ )
i_capabilities |= CPU_CAPABILITY_FPU;
# ifdef CAN_COMPILE_ALTIVEC
signal( SIGILL, IllegalSignalHandler );
sighandler_t pf_sigill = signal( SIGILL, SigHandler );
i_capabilities |= CPU_CAPABILITY_FPU;
i_illegal = 0;
vlc_mutex_lock( p_this->p_vlc->p_global_lock );
if( setjmp( env ) == 0 )
{
asm volatile ("mtspr 256, %0\n\t"
......@@ -262,14 +274,13 @@ u32 __CPUCapabilities( vlc_object_t *p_this )
:
: "r" (-1));
}
vlc_mutex_unlock( p_this->p_vlc->p_global_lock );
if( i_illegal == 0 )
{
i_capabilities |= CPU_CAPABILITY_ALTIVEC;
}
signal( SIGILL, NULL );
signal( SIGILL, pf_sigill );
# endif
return i_capabilities;
......@@ -287,12 +298,12 @@ u32 __CPUCapabilities( vlc_object_t *p_this )
}
/*****************************************************************************
* IllegalSignalHandler: system signal handler
* SigHandler: system signal handler
*****************************************************************************
* This function is called when an illegal instruction signal is received by
* the program. We use this function to test OS and CPU capabilities
*****************************************************************************/
static void IllegalSignalHandler( int i_signal )
static void SigHandler( int i_signal )
{
/* Acknowledge the signal received */
i_illegal = 1;
......
......@@ -2,11 +2,12 @@
* vlc.c: the vlc player
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: vlc.c,v 1.8 2002/08/08 00:35:11 sam Exp $
* $Id: vlc.c,v 1.9 2002/08/19 11:13:45 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
* Gildas Bazin <gbazin@netcourrier.com>
* Lots of other people, see the libvlc AUTHORS file
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -22,19 +23,30 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include <signal.h> /* SIGHUP, SIGINT, SIGKILL */
#include <stdio.h> /* fprintf() */
#include <stdlib.h> /* putenv(), strtol(), */
#include <signal.h> /* SIGHUP, SIGINT, SIGKILL */
#include <vlc/vlc.h>
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
#ifndef WIN32
static void SigHandler ( int i_signal );
#endif
/*****************************************************************************
* main: parse command line, start interface and spawn threads
*****************************************************************************/
int main(int i_argc, char *ppsz_argv[])
int main( int i_argc, char *ppsz_argv[] )
{
vlc_error_t err;
fprintf( stderr, COPYRIGHT_MESSAGE "\n" );
#ifdef SYS_LINUX
# ifdef DEBUG
/* Activate malloc checking routines to detect heap corruptions. */
......@@ -45,14 +57,28 @@ int main(int i_argc, char *ppsz_argv[])
# endif
#endif
/* Create the vlc structure */
/* Create a libvlc structure */
err = vlc_create();
if( err != VLC_SUCCESS )
{
return err;
}
/* Initialize vlc */
#ifndef WIN32
/* Set the signal handlers. SIGTERM is not intercepted, because we need at
* least one method to kill the program when all other methods failed, and
* when we don't want to use SIGKILL.
* Note that we set the signals after the vlc_create call. */
signal( SIGINT, SigHandler );
signal( SIGHUP, SigHandler );
signal( SIGQUIT, SigHandler );
/* Other signals */
signal( SIGALRM, SIG_IGN );
signal( SIGPIPE, SIG_IGN );
#endif
/* Initialize libvlc */
err = vlc_init( i_argc, ppsz_argv );
if( err != VLC_SUCCESS )
{
......@@ -60,7 +86,7 @@ int main(int i_argc, char *ppsz_argv[])
return err;
}
/* Run vlc, in non-blocking mode */
/* Run libvlc, in non-blocking mode */
err = vlc_run();
/* Add background interfaces */
......@@ -83,9 +109,52 @@ int main(int i_argc, char *ppsz_argv[])
/* Finish all threads */
vlc_end();
/* Destroy the vlc structure */
/* Destroy the libvlc structure */
vlc_destroy();
return err;
}
#ifndef WIN32
/*****************************************************************************
* SigHandler: system signal handler
*****************************************************************************
* This function is called when a fatal signal is received by the program.
* It tries to end the program in a clean way.
*****************************************************************************/
static void SigHandler( int i_signal )
{
static mtime_t abort_time = 0;
static volatile vlc_bool_t b_die = VLC_FALSE;
/* Once a signal has been trapped, the termination sequence will be
* armed and subsequent signals will be ignored to avoid sending signals
* to a libvlc structure having been destroyed */
if( !b_die )
{
b_die = VLC_TRUE;
abort_time = mdate();
fprintf( stderr, "signal %d received, terminating vlc - do it "
"again in case it gets stuck\n", i_signal );
/* Acknowledge the signal received */
vlc_die();
}
else if( mdate() > abort_time + 1000000 )
{
/* If user asks again 1 second later, die badly */
signal( SIGINT, SIG_DFL );
signal( SIGHUP, SIG_DFL );
signal( SIGQUIT, SIG_DFL );
signal( SIGALRM, SIG_DFL );
signal( SIGPIPE, SIG_DFL );
fprintf( stderr, "user insisted too much, dying badly\n" );
exit( 1 );
}
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment