summaryrefslogtreecommitdiffstats
path: root/src/misc/util/utilSignal.c
diff options
context:
space:
mode:
authorBaruch Sterin <baruchs@gmail.com>2011-02-27 18:33:56 -0800
committerBaruch Sterin <baruchs@gmail.com>2011-02-27 18:33:56 -0800
commit34d59b0b91f09b35b7c3b4e74411f11b8b3994cc (patch)
treea721b34849df3243b145ba62b504ed41ab618dbc /src/misc/util/utilSignal.c
parent02081dba6779fbd247d1e62d5dc6db2097acc8e7 (diff)
downloadabc-34d59b0b91f09b35b7c3b4e74411f11b8b3994cc.tar.gz
abc-34d59b0b91f09b35b7c3b4e74411f11b8b3994cc.tar.bz2
abc-34d59b0b91f09b35b7c3b4e74411f11b8b3994cc.zip
fixes to pyabc kill mechanism
Diffstat (limited to 'src/misc/util/utilSignal.c')
-rw-r--r--src/misc/util/utilSignal.c474
1 files changed, 14 insertions, 460 deletions
diff --git a/src/misc/util/utilSignal.c b/src/misc/util/utilSignal.c
index 3549dbec..eeff504a 100644
--- a/src/misc/util/utilSignal.c
+++ b/src/misc/util/utilSignal.c
@@ -4,9 +4,9 @@
SystemName [ABC: Logic synthesis and verification system.]
- PackageName [Signal handling utilities.]
+ PackageName []
- Synopsis [Signal handling utilities.]
+ Synopsis []
Author [Baruch Sterin]
@@ -18,19 +18,15 @@
***********************************************************************/
-#include <main.h>
#include <stdlib.h>
-#include <signal.h>
#include "abc_global.h"
-#include "hashGen.h"
#include "utilSignal.h"
-#ifndef _MSC_VER
-
+#ifdef _MSC_VER
+#define remove _remove
+#else
#include <unistd.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/wait.h>
+#endif
ABC_NAMESPACE_IMPL_START
@@ -38,478 +34,36 @@ ABC_NAMESPACE_IMPL_START
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static Hash_Gen_t* watched_pid_hash = NULL;
-static Hash_Gen_t* watched_tmp_files_hash = NULL;
-
-static sigset_t old_procmask;
-
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
-/**Function*************************************************************
-
- Synopsis []
-
- Description [Kills all watched child processes and remove all watched termporary files.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
-void Util_SignalCleanup()
-{
- int i;
- Hash_Gen_Entry_t* pEntry;
-
- // kill all watched child processes
- Hash_GenForEachEntry(watched_pid_hash, pEntry, i)
- {
- pid_t pid = (pid_t)(ABC_PTRINT_T)pEntry->key;
- pid_t ppid = (pid_t)(ABC_PTRINT_T)pEntry->data;
-
- if (getpid() == ppid)
- {
- kill(pid, SIGINT);
- }
- }
-
- // remove watched temporary files
- Hash_GenForEachEntry(watched_tmp_files_hash, pEntry, i)
- {
- const char* fname = (const char*)pEntry->key;
- pid_t ppid = (pid_t)(ABC_PTRINT_T)pEntry->data;
-
- if( getpid() == ppid )
- {
- remove(fname);
- }
- }
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description [Sets up data structures needed for cleanup in signal handler.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
-void Util_SignalStartHandler()
-{
- watched_pid_hash = Hash_GenAlloc(100, Hash_DefaultHashFuncInt, Hash_DefaultCmpFuncInt, 0);
- watched_tmp_files_hash = Hash_GenAlloc(100, Hash_DefaultHashFuncStr, (Hash_GenCompFunction_t)strcmp, 1);
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description [Frees data structures used for clean up in signal handler.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
-void Util_SignalResetHandler()
-{
- sigset_t procmask, old_procmask;
-
- sigemptyset(&procmask);
- sigaddset(&procmask, SIGINT);
-
- sigprocmask(SIG_BLOCK, &procmask, &old_procmask);
-
- Hash_GenFree(watched_pid_hash);
- watched_pid_hash = Hash_GenAlloc(100, Hash_DefaultHashFuncInt, Hash_DefaultCmpFuncInt, 0);
-
- Hash_GenFree(watched_tmp_files_hash);
- watched_tmp_files_hash = Hash_GenAlloc(100, Hash_DefaultHashFuncStr, (Hash_GenCompFunction_t)strcmp, 1);
-
- sigprocmask(SIG_SETMASK, &old_procmask, NULL);
-}
-
-void Util_SignalStopHandler()
-{
- Hash_GenFree(watched_pid_hash);
- watched_pid_hash = NULL;
-
- Hash_GenFree(watched_tmp_files_hash);
- watched_tmp_files_hash = NULL;
-}
-
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description [Blocks SIGINT. For use when updating watched processes and temporary files to prevent race conditions with the signal handler.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
-static int nblocks = 0;
-
-void Util_SignalBlockSignals()
-{
- sigset_t procmask;
-
- assert(nblocks==0);
- nblocks ++ ;
-
- sigemptyset(&procmask);
- sigaddset(&procmask, SIGINT);
-
- sigprocmask(SIG_BLOCK, &procmask, &old_procmask);
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description [Unblocks SIGINT after a call to Util_SignalBlockSignals.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
-void Util_SignalUnblockSignals()
-{
- assert( nblocks==1);
- nblocks--;
-
- sigprocmask(SIG_SETMASK, &old_procmask, NULL);
-}
-
-
-static void watch_tmp_file(const char* fname)
-{
- if( watched_tmp_files_hash != NULL )
- {
- Hash_GenWriteEntry(watched_tmp_files_hash, Extra_UtilStrsav(fname), (void*)getpid() );
- }
-}
-
-static void unwatch_tmp_file(const char* fname)
-{
- if ( watched_tmp_files_hash )
- {
- assert( Hash_GenExists(watched_tmp_files_hash, (void*)fname) );
- Hash_GenRemove(watched_tmp_files_hash, (void*)fname);
- assert( !Hash_GenExists(watched_tmp_files_hash, (void*)fname) );
- }
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description [Adds a process id to the list of processes that should be killed in a signal handler.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
-void Util_SignalAddChildPid(int pid)
-{
- if ( watched_pid_hash )
- {
- Hash_GenWriteEntry(watched_pid_hash, (void*)pid, (void*)getpid());
- }
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description [Removes a process id from the list of processes that should be killed in a signal handler.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
-void Util_SignalRemoveChildPid(int pid)
-{
- if ( watched_pid_hash )
- {
- Hash_GenRemove(watched_pid_hash, (void*)pid);
- }
-}
-
-// a dummy signal hanlder to make sure that SIGCHLD and SIGINT will cause sigsuspend() to return
-static void null_sig_handler(int signum)
-{
-}
-
-
-// enusre that sigsuspend() returns when signal signum occurs -- sigsuspend() does not return if a signal is ignored
-static void replace_sighandler(int signum, struct sigaction* old_sa, int replace_dfl)
-{
- sigaction(signum, NULL, old_sa);
-
- if( old_sa->sa_handler == SIG_IGN || old_sa->sa_handler==SIG_DFL && replace_dfl)
- {
- struct sigaction sa;
- memset(&sa, 0, sizeof(sa));
-
- sa.sa_handler = null_sig_handler;
-
- sigaction(signum, &sa, old_sa);
- }
-}
-
-//
-static int do_waitpid(pid_t pid, sigset_t* old_procmask)
-{
- int status;
-
- struct sigaction sigint_sa;
- struct sigaction sigchld_sa;
- sigset_t waitmask;
-
- // ensure SIGINT and SIGCHLD are not blocked during sigsuspend()
- memcpy(&waitmask, old_procmask, sizeof(sigset_t));
-
- sigdelset(&waitmask, SIGINT);
- sigdelset(&waitmask, SIGCHLD);
-
- // ensure sigsuspend() returns if SIGINT or SIGCHLD occur, and save the current settings for SIGCHLD and SIGINT
-
- replace_sighandler(SIGINT, &sigint_sa, 0);
- replace_sighandler(SIGCHLD, &sigchld_sa, 1);
-
- for(;;)
- {
- int rc;
-
- // wait for a signal -- returns if SIGINT or SIGCHLD (or any other signal that is unblocked and not ignored) occur
- sigsuspend(&waitmask);
-
- // check if pid has terminated
- rc = waitpid(pid, &status, WNOHANG);
-
- // stop if terminated or some other error occurs
- if( rc > 0 || rc == -1 && errno!=EINTR )
- {
- break;
- }
- }
-
- // process is dead, should no longer be watched
- Util_SignalRemoveChildPid(pid);
-
- // restore original behavior of SIGINT and SIGCHLD
- sigaction(SIGINT, &sigint_sa, NULL);
- sigaction(SIGCHLD, &sigchld_sa, NULL);
-
- return status;
-}
-
-static int do_system(const char* cmd, sigset_t* old_procmask)
-{
- int pid;
-
- pid = fork();
-
- if (pid == -1)
- {
- // fork failed
- return -1;
- }
- else if( pid == 0)
- {
- // child process
- sigprocmask(SIG_SETMASK, old_procmask, NULL);
- execl("/bin/sh", "sh", "-c", cmd, NULL);
- _exit(127);
- }
-
- Util_SignalAddChildPid(pid);
-
- return do_waitpid(pid, old_procmask);
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description [Replaces system() with a function that allows SIGINT to interrupt.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
-int Util_SignalSystem(const char* cmd)
-{
- int status;
-
- sigset_t procmask;
- sigset_t old_procmask;
-
- // if signal handler is not installed, run the original system()
- if ( ! watched_pid_hash && ! watched_tmp_files_hash )
- return system(cmd);
-
- // block SIGINT and SIGCHLD
- sigemptyset(&procmask);
-
- sigaddset(&procmask, SIGINT);
- sigaddset(&procmask, SIGCHLD);
-
- sigprocmask(SIG_BLOCK, &procmask, &old_procmask);
-
- // call the actual function
- status = do_system(cmd, &old_procmask);
-
- // restore signal block mask
- sigprocmask(SIG_SETMASK, &old_procmask, NULL);
- return status;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
-#else /* #ifndef _MSC_VER */
-
-#include "abc_global.h"
-
-ABC_NAMESPACE_IMPL_START
-
-void Util_SignalCleanup()
-{
-}
-
-void Util_SignalStartHandler()
-{
-}
-
-void Util_SignalResetHandler()
-{
-}
-
-void Util_SignalStopHandler()
-{
-}
-
-void Util_SignalBlockSignals()
-{
-}
-
-void Util_SignalUnblockSignals()
-{
-}
-
-void watch_tmp_file(const char* fname)
-{
-}
-
-void unwatch_tmp_file(const char* fname)
-{
-}
-
-void Util_SignalAddChildPid(int pid)
-{
-}
-
-void Util_SignalRemoveChildPid(int pid)
-{
-}
+#ifndef ABC_PYTHON_EMBED
int Util_SignalSystem(const char* cmd)
{
return system(cmd);
}
-#endif /* #ifdef _MSC_VER */
-
int tmpFile(const char* prefix, const char* suffix, char** out_name);
-/**Function*************************************************************
-
- Synopsis []
-
- Description [Create a temporary file and add it to the list of files to be cleaned up in the signal handler.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
int Util_SignalTmpFile(const char* prefix, const char* suffix, char** out_name)
{
- int fd;
-
- Util_SignalBlockSignals();
-
- fd = tmpFile(prefix, suffix, out_name);
-
- if ( fd != -1 )
- {
- watch_tmp_file( *out_name );
- }
-
- Util_SignalUnblockSignals();
-
- return fd;
+ return tmpFile(prefix, suffix, out_name);
}
-/**Function*************************************************************
-
- Synopsis []
-
- Description [Remove a temporary file (and remove it from the watched files list.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
void Util_SignalTmpFileRemove(const char* fname, int fLeave)
{
- Util_SignalBlockSignals();
-
- unwatch_tmp_file(fname);
-
if (! fLeave)
{
remove(fname);
}
-
- Util_SignalUnblockSignals();
}
+#endif /* ABC_PYTHON_EMBED */
+
ABC_NAMESPACE_IMPL_END
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////