Factor out VG_(exit_now) to contain the syscall incantation to terminate
the process. Make ML_(am_exit) and VG_(exit) use it, thereby avoiding 
double maintenance.
Introduce libcbase_assert macro and use it in VG_(strncpy_safely) to 
document the case that function cannot handle.
Add stub functions to memcheck/tests/unit_libcbase.c to satisfy new
dependencies.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14185 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_aspacemgr/aspacemgr-common.c b/coregrind/m_aspacemgr/aspacemgr-common.c
index b8d694d..96f5ecf 100644
--- a/coregrind/m_aspacemgr/aspacemgr-common.c
+++ b/coregrind/m_aspacemgr/aspacemgr-common.c
@@ -54,14 +54,7 @@
 __attribute__ ((noreturn))
 void ML_(am_exit)( Int status )
 {
-#  if defined(VGO_linux)
-   (void)VG_(do_syscall1)(__NR_exit_group, status);
-#  endif
-   (void)VG_(do_syscall1)(__NR_exit, status);
-   /* Why are we still alive here? */
-   /*NOTREACHED*/
-   *(volatile Int *)0 = 'x';
-   aspacem_assert(2+2 == 5);
+   VG_(exit_now) (status);
 }
 
 void ML_(am_barf) ( const HChar* what )
diff --git a/coregrind/m_aspacemgr/priv_aspacemgr.h b/coregrind/m_aspacemgr/priv_aspacemgr.h
index 4ef4323..730e536 100644
--- a/coregrind/m_aspacemgr/priv_aspacemgr.h
+++ b/coregrind/m_aspacemgr/priv_aspacemgr.h
@@ -47,6 +47,8 @@
                                  // VG_IS_PAGE_ALIGNED
                                  // VG_PGROUNDDN, VG_PGROUNDUP
 
+#include "pub_core_libcassert.h" // VG_(exit_now)
+
 #include "pub_core_syscall.h"    // VG_(do_syscallN)
                                  // VG_(mk_SysRes_Error)
                                  // VG_(mk_SysRes_Success)
diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c
index f8a957b..df11fba 100644
--- a/coregrind/m_libcassert.c
+++ b/coregrind/m_libcassert.c
@@ -256,6 +256,15 @@
    }
    exit_called = True;
 
+   VG_(exit_now) (status);
+}
+
+/* Call the appropriate system call and nothing else. This function should
+   be called in places where the dependencies of VG_(exit) need to be
+   avoided. */
+__attribute__ ((__noreturn__))
+void VG_(exit_now)( Int status )
+{
 #if defined(VGO_linux)
    (void)VG_(do_syscall1)(__NR_exit_group, status );
 #elif defined(VGO_darwin)
diff --git a/coregrind/m_libcbase.c b/coregrind/m_libcbase.c
index 61f6fef..56a7039 100644
--- a/coregrind/m_libcbase.c
+++ b/coregrind/m_libcbase.c
@@ -29,8 +29,34 @@
 */
 
 #include "pub_core_basics.h"
+#include "pub_core_libcassert.h"    // VG_(exit_now)
+#include "pub_core_debuglog.h"      // VG_(debugLog)
 #include "pub_core_libcbase.h"
 
+
+/* ---------------------------------------------------------------------
+   Assert machinery for use in this file. VG_(assert) cannot be called
+   here due to cyclic dependencies.
+   ------------------------------------------------------------------ */
+#define libcbase_assert(expr)                             \
+  ((void) ((expr) ? 0 :                                   \
+           (ML_(libcbase_assert_fail)(#expr,              \
+                                __FILE__, __LINE__,       \
+                                __PRETTY_FUNCTION__))))
+
+static void ML_(libcbase_assert_fail)( const HChar *expr,
+                                       const HChar *file,
+                                       Int line, 
+                                       const HChar *fn )
+{
+   VG_(debugLog)(0, "libcbase", 
+                    "Valgrind: FATAL: assertion failed:\n");
+   VG_(debugLog)(0, "libcbase", "  %s\n", expr);
+   VG_(debugLog)(0, "libcbase", "  at %s:%d (%s)\n", file, line, fn);
+   VG_(debugLog)(0, "libcbase", "Exiting now.\n");
+   VG_(exit_now)(1);
+}
+
 /* ---------------------------------------------------------------------
    HChar functions.
    ------------------------------------------------------------------ */
@@ -276,6 +302,8 @@
    zero termination. */
 void VG_(strncpy_safely) ( HChar* dest, const HChar* src, SizeT ndest )
 {
+   libcbase_assert(ndest > 0);
+
    SizeT i = 0;
    while (True) {
       dest[i] = 0;
diff --git a/coregrind/pub_core_libcassert.h b/coregrind/pub_core_libcassert.h
index e9326a4..de4b3cc 100644
--- a/coregrind/pub_core_libcassert.h
+++ b/coregrind/pub_core_libcassert.h
@@ -69,6 +69,10 @@
 /* Exits with status as client exit code. */
 extern void VG_(client_exit)( Int status );
 
+/* Lightweight exit without any dependencies. */
+__attribute__ ((__noreturn__))
+extern void VG_(exit_now)( Int status );
+
 /* Called when some unhandleable client behaviour is detected.
    Prints a msg and aborts. */
 extern void VG_(unimplemented) ( const HChar* msg )
diff --git a/memcheck/tests/unit_libcbase.c b/memcheck/tests/unit_libcbase.c
index 019b67a..33542ce 100644
--- a/memcheck/tests/unit_libcbase.c
+++ b/memcheck/tests/unit_libcbase.c
@@ -3,11 +3,30 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stddef.h>
 
 #include "pub_tool_basics.h"  /* UInt et al, needed for pub_tool_vki.h */
 #include "pub_tool_vki.h"
 #include "m_libcbase.c"
 
+/* Provide a stub to not have to pull in m_debuglog.c */
+void VG_(debugLog) ( Int level, const HChar* modulename,
+                                const HChar* format, ... )
+{
+   va_list args;
+   va_start(args, format);
+   fprintf(stderr, "debuglog: %s: ", modulename);
+   vfprintf(stderr, format, args);
+   va_end(args);
+}
+
+/* Provide a stub to not have to pull in m_libcassert.c */
+void VG_(exit_now)( Int status )
+{
+   exit(status);
+}
+
+
 #define  CHECK(x) \
    if (!x) { fprintf(stderr, "failure: %s:%d\n", __FILE__, __LINE__); }