diff -rNu phobos-original-2006-02-22/internal/dmain2.d phobos-disposable-2006-02-22/internal/dmain2.d --- phobos-original-2006-02-22/internal/dmain2.d 2006-02-15 13:48:54.000000000 -0600 +++ phobos-disposable-2006-02-22/internal/dmain2.d 2006-02-22 22:49:57.000000000 -0600 @@ -9,6 +9,10 @@ import std.c.stdlib; import std.string; +private import std.disposable; + +version (linux) import std.c.linux.linux; + extern (C) void _STI_monitor_staticctor(); extern (C) void _STD_monitor_staticdtor(); extern (C) void _STI_critical_init(); @@ -33,7 +37,6 @@ extern (C) int main(int argc, char **argv) { - char[] *am; char[][] args; int i; int result; @@ -45,7 +48,7 @@ _STI_monitor_staticctor(); _STI_critical_init(); gc_init(); - am = cast(char[] *) malloc(argc * (char[]).sizeof); + _dmain2_am = cast(char[] *) malloc(argc * (char[]).sizeof); // BUG: alloca() conflicts with try-catch-finally stack unwinding //am = (char[] *) alloca(argc * (char[]).sizeof); } @@ -53,9 +56,12 @@ { gc_init(); _minit(); - am = cast(char[] *) alloca(argc * (char[]).sizeof); + _dmain2_am = cast(char[] *) alloca(argc * (char[]).sizeof); } + // Set hooks for guaranteed disposable object destruction + setupForDisposal(); + try { _moduleCtor(); @@ -64,27 +70,34 @@ for (i = 0; i < argc; i++) { int len = strlen(argv[i]); - am[i] = argv[i][0 .. len]; + _dmain2_am[i] = argv[i][0 .. len]; } - args = am[0 .. argc]; + args = _dmain2_am[0 .. argc]; - result = main(args); - _moduleDtor(); - gc_term(); + mainResult = main(args); } catch (Object o) { printf("Error: "); o.print(); - exit(EXIT_FAILURE); + try { + while (_disposeObjects()) {} + _phobosTerminate(); + } catch (Object o) { + printf("Error while terminating due to error: "); + o.print(); + exit(EXIT_FAILURE); + } } - version (linux) - { - free(am); - _STD_critical_term(); - _STD_monitor_staticdtor(); + + try { + while (_disposeObjects()) {} + } catch (Object o) { + printf("Error: "); + o.print(); } - return result; -} + _phobosTerminate(); + return mainResult; +} Binary files phobos-original-2006-02-22/internal/gc/dmgc.a and phobos-disposable-2006-02-22/internal/gc/dmgc.a differ Binary files phobos-original-2006-02-22/internal/gc/gc.o and phobos-disposable-2006-02-22/internal/gc/gc.o differ Binary files phobos-original-2006-02-22/internal/gc/gcbits.o and phobos-disposable-2006-02-22/internal/gc/gcbits.o differ Binary files phobos-original-2006-02-22/internal/gc/gclinux.o and phobos-disposable-2006-02-22/internal/gc/gclinux.o differ Binary files phobos-original-2006-02-22/internal/gc/gcx.o and phobos-disposable-2006-02-22/internal/gc/gcx.o differ Binary files phobos-original-2006-02-22/libphobos.a and phobos-disposable-2006-02-22/libphobos.a differ diff -rNu phobos-original-2006-02-22/linux.mak phobos-disposable-2006-02-22/linux.mak --- phobos-original-2006-02-22/linux.mak 2006-02-15 13:48:52.000000000 -0600 +++ phobos-disposable-2006-02-22/linux.mak 2006-02-22 22:55:59.000000000 -0600 @@ -15,7 +15,7 @@ DFLAGS=-O -release #DFLAGS=-unittest -CC=gcc +CC=gcc-3.3 #DMD=/dmd/bin/dmd DMD=dmd @@ -52,12 +52,11 @@ cast.o path.o string.o memset.o math.o mmfile.o \ outbuffer.o ctype.o regexp.o random.o linux.o linuxsocket.o \ stream.o cstream.o switcherr.o array.o gc.o \ - qsort.o thread.o obj.o utf.o uri.o \ + qsort.o thread.o obj.o utf.o uri.o disposable.o demangle.o \ crc32.o conv.o arraycast.o errno.o alloca.o cmath2.o \ process.o syserror.o \ socket.o socketstream.o stdarg.o stdio.o format.o \ perf.o openrj.o uni.o trace.o boxer.o \ - demangle.o cover.o mangle.o \ ti_wchar.o ti_uint.o ti_short.o ti_ushort.o \ ti_byte.o ti_ubyte.o ti_long.o ti_ulong.o ti_ptr.o \ ti_float.o ti_double.o ti_real.o ti_delegate.o \ @@ -69,7 +68,7 @@ ti_Afloat.o ti_Adouble.o ti_Areal.o \ ti_Acfloat.o ti_Acdouble.o ti_Acreal.o \ ti_Abit.o ti_void.o \ - date.o dateparse.o llmath.o math2.o Czlib.o Dzlib.o zip.o recls.o + date.o dateparse.o llmath.o math2.o Czlib.o Dzlib.o zip.o ZLIB_OBJS= etc/c/zlib/adler32.o etc/c/zlib/compress.o \ etc/c/zlib/crc32.o etc/c/zlib/gzio.o \ @@ -78,14 +77,6 @@ etc/c/zlib/inflate.o etc/c/zlib/infback.o \ etc/c/zlib/inftrees.o etc/c/zlib/inffast.o -RECLS_OBJS= etc/c/recls/recls_api.o \ - etc/c/recls/recls_fileinfo.o \ - etc/c/recls/recls_internal.o \ - etc/c/recls/recls_util.o \ - etc/c/recls/recls_api_unix.o \ - etc/c/recls/recls_fileinfo_unix.o \ - etc/c/recls/recls_util_unix.o - GC_OBJS= internal/gc/gc.o internal/gc/gcx.o \ internal/gc/gcbits.o internal/gc/gclinux.o @@ -97,10 +88,10 @@ std/outbuffer.d std/math2.d std/thread.d std/md5.d std/base64.d \ std/asserterror.d std/dateparse.d std/outofmemory.d std/mmfile.d \ std/intrinsic.d std/array.d std/switcherr.d std/syserror.d \ - std/regexp.d std/random.d std/stream.d std/process.d std/recls.d \ + std/regexp.d std/random.d std/stream.d std/process.d \ std/socket.d std/socketstream.d std/loader.d std/stdarg.d \ std/stdio.d std/format.d std/perf.d std/openrj.d std/uni.d \ - std/boxer.d std/cstream.d std/demangle.d std/cover.d + std/boxer.d std/cstream.d std/disposable.d std/demangle.d SRC_STD_C= std/c/process.d std/c/stdlib.d std/c/time.d std/c/stdio.d \ std/c/math.d std/c/stdarg.d std/c/stddef.d @@ -137,10 +128,10 @@ internal/memset.d internal/arraycast.d internal/aaA.d internal/adi.d \ internal/dmain2.d internal/cast.d internal/qsort.d internal/deh2.d \ internal/cmath2.d internal/obj.d internal/mars.h internal/aApply.d \ - internal/object.d internal/trace.d internal/qsort2.d internal/match.d + internal/object.d internal/trace.d internal/qsort2.d SRC_STD_WIN= std/windows/registry.d \ - std/windows/iunknown.d std/windows/charset.d + std/windows/iunknown.d SRC_STD_C_WIN= std/c/windows/windows.d std/c/windows/com.d \ std/c/windows/winsock.d @@ -148,7 +139,7 @@ SRC_STD_C_LINUX= std/c/linux/linux.d std/c/linux/linuxextern.d \ std/c/linux/socket.d -SRC_ETC= etc/gamma.d etc/realtest.d +SRC_ETC= SRC_ETC_C= etc/c/zlib.d @@ -195,167 +186,9 @@ internal/gc/win32.mak \ internal/gc/linux.mak -SRC_STLSOFT= \ - etc/c/stlsoft/stlsoft_null_mutex.h \ - etc/c/stlsoft/unixstl_string_access.h \ - etc/c/stlsoft/unixstl.h \ - etc/c/stlsoft/winstl_tls_index.h \ - etc/c/stlsoft/unixstl_environment_variable.h \ - etc/c/stlsoft/unixstl_functionals.h \ - etc/c/stlsoft/unixstl_current_directory.h \ - etc/c/stlsoft/unixstl_limits.h \ - etc/c/stlsoft/unixstl_current_directory_scope.h \ - etc/c/stlsoft/unixstl_filesystem_traits.h \ - etc/c/stlsoft/unixstl_findfile_sequence.h \ - etc/c/stlsoft/unixstl_glob_sequence.h \ - etc/c/stlsoft/winstl.h \ - etc/c/stlsoft/winstl_atomic_functions.h \ - etc/c/stlsoft/stlsoft_cccap_gcc.h \ - etc/c/stlsoft/stlsoft_lock_scope.h \ - etc/c/stlsoft/unixstl_thread_mutex.h \ - etc/c/stlsoft/unixstl_spin_mutex.h \ - etc/c/stlsoft/unixstl_process_mutex.h \ - etc/c/stlsoft/stlsoft_null.h \ - etc/c/stlsoft/stlsoft_nulldef.h \ - etc/c/stlsoft/winstl_thread_mutex.h \ - etc/c/stlsoft/winstl_spin_mutex.h \ - etc/c/stlsoft/winstl_system_version.h \ - etc/c/stlsoft/winstl_findfile_sequence.h \ - etc/c/stlsoft/unixstl_readdir_sequence.h \ - etc/c/stlsoft/stlsoft.h \ - etc/c/stlsoft/stlsoft_static_initialisers.h \ - etc/c/stlsoft/stlsoft_iterator.h \ - etc/c/stlsoft/stlsoft_cccap_dmc.h \ - etc/c/stlsoft/winstl_filesystem_traits.h - -SRC_RECLS= \ - etc/c/recls/recls_compiler.h \ - etc/c/recls/recls_language.h \ - etc/c/recls/recls_unix.h \ - etc/c/recls/recls_retcodes.h \ - etc/c/recls/recls_assert.h \ - etc/c/recls/recls_platform.h \ - etc/c/recls/recls_win32.h \ - etc/c/recls/recls.h \ - etc/c/recls/recls_util.h \ - etc/c/recls/recls_compiler_dmc.h \ - etc/c/recls/recls_compiler_gcc.h \ - etc/c/recls/recls_platform_types.h \ - etc/c/recls/recls_internal.h \ - etc/c/recls/recls_debug.h \ - etc/c/recls/recls_fileinfo_win32.cpp \ - etc/c/recls/recls_api_unix.cpp \ - etc/c/recls/recls_api.cpp \ - etc/c/recls/recls_util_win32.cpp \ - etc/c/recls/recls_util_unix.cpp \ - etc/c/recls/recls_util.cpp \ - etc/c/recls/recls_internal.cpp \ - etc/c/recls/recls_fileinfo.cpp \ - etc/c/recls/recls_defs.h \ - etc/c/recls/recls_fileinfo_unix.cpp \ - etc/c/recls/recls_api_win32.cpp \ - etc/c/recls/win32.mak \ - etc/c/recls/linux.mak \ - etc/c/recls/recls.lib - -SRC_STLSOFT_NEW= \ - etc/c/stlsoft/winstl_file_path_buffer.h \ - etc/c/stlsoft/inetstl_connection.h \ - etc/c/stlsoft/inetstl_filesystem_traits.h \ - etc/c/stlsoft/inetstl_findfile_sequence.h \ - etc/c/stlsoft/inetstl_searchspec_sequence.h \ - etc/c/stlsoft/inetstl_session.h \ - etc/c/stlsoft/stlsoft.h \ - etc/c/stlsoft/stlsoft_allocator_base.h \ - etc/c/stlsoft/inetstl.h \ - etc/c/stlsoft/stlsoft_auto_buffer.h \ - etc/c/stlsoft/stlsoft_cccap_dmc.h \ - etc/c/stlsoft/stlsoft_cccap_gcc.h \ - etc/c/stlsoft/stlsoft_char_traits.h \ - etc/c/stlsoft/stlsoft_constraints.h \ - etc/c/stlsoft/stlsoft_exceptions.h \ - etc/c/stlsoft/stlsoft_iterator.h \ - etc/c/stlsoft/stlsoft_meta.h \ - etc/c/stlsoft/stlsoft_new_allocator.h \ - etc/c/stlsoft/stlsoft_any_caster.h \ - etc/c/stlsoft/stlsoft_nulldef.h \ - etc/c/stlsoft/stlsoft_sap_cast.h \ - etc/c/stlsoft/stlsoft_searchspec_sequence.h \ - etc/c/stlsoft/stlsoft_sign_traits.h \ - etc/c/stlsoft/stlsoft_simple_algorithms.h \ - etc/c/stlsoft/stlsoft_simple_string.h \ - etc/c/stlsoft/stlsoft_size_traits.h \ - etc/c/stlsoft/stlsoft_string_access.h \ - etc/c/stlsoft/stlsoft_string_tokeniser.h \ - etc/c/stlsoft/stlsoft_type_traits.h \ - etc/c/stlsoft/unixstl.h \ - etc/c/stlsoft/unixstl_filesystem_traits.h \ - etc/c/stlsoft/unixstl_file_path_buffer.h \ - etc/c/stlsoft/unixstl_glob_sequence.h \ - etc/c/stlsoft/unixstl_string_access.h \ - etc/c/stlsoft/unixstl_thread_mutex.h \ - etc/c/stlsoft/winstl.h \ - etc/c/stlsoft/winstl_atomic_functions.h \ - etc/c/stlsoft/winstl_char_conversions.h \ - etc/c/stlsoft/winstl_filesystem_traits.h \ - etc/c/stlsoft/winstl_spin_mutex.h \ - etc/c/stlsoft/winstl_findfile_sequence.h \ - etc/c/stlsoft/winstl_processheap_allocator.h \ - etc/c/stlsoft/winstl_system_version.h \ - etc/c/stlsoft/stlsoft_null.h - -SRC_RECLS_NEW= \ - etc/c/recls/recls_compiler_gcc.h \ - etc/c/recls/recls_retcodes.h \ - etc/c/recls/EntryFunctions.h \ - etc/c/recls/recls_platform_types.h \ - etc/c/recls/recls.h \ - etc/c/recls/recls_wininet_dl.h \ - etc/c/recls/ReclsFileSearch.h \ - etc/c/recls/ReclsFileSearchDirectoryNode_unix.cpp \ - etc/c/recls/ReclsFileSearchDirectoryNode_unix.h \ - etc/c/recls/ReclsFileSearchDirectoryNode_win32.cpp \ - etc/c/recls/ReclsFileSearchDirectoryNode_win32.h \ - etc/c/recls/recls_wininet_dl.cpp \ - etc/c/recls/ReclsFileSearch_unix.cpp \ - etc/c/recls/ReclsFileSearch_win32.cpp \ - etc/c/recls/recls_win32.h \ - etc/c/recls/ReclsFtpSearch.h \ - etc/c/recls/ReclsFtpSearchDirectoryNode_win32.cpp \ - etc/c/recls/ReclsFtpSearchDirectoryNode_win32.h \ - etc/c/recls/recls_util_win32.cpp \ - etc/c/recls/ReclsFtpSearch_win32.cpp \ - etc/c/recls/recls_util_unix.cpp \ - etc/c/recls/recls_api.cpp \ - etc/c/recls/recls_util.h \ - etc/c/recls/recls_api_unix.cpp \ - etc/c/recls/recls_api_win32.cpp \ - etc/c/recls/recls_util.cpp \ - etc/c/recls/recls_assert.h \ - etc/c/recls/recls_compiler.h \ - etc/c/recls/recls_compiler_dmc.h \ - etc/c/recls/recls_platform.h \ - etc/c/recls/recls_debug.h \ - etc/c/recls/recls_defs.h \ - etc/c/recls/recls_fileinfo.cpp \ - etc/c/recls/recls_fileinfo_unix.cpp \ - etc/c/recls/recls_fileinfo_win32.cpp \ - etc/c/recls/recls_unix.h \ - etc/c/recls/recls_ftp.h \ - etc/c/recls/recls_ftp_api_win32.cpp \ - etc/c/recls/recls_internal.cpp \ - etc/c/recls/recls_internal.h \ - etc/c/recls/recls_roots_win32.cpp \ - etc/c/recls/recls_language.h \ - etc/c/recls/recls_roots_unix.cpp \ - etc/c/recls/win32.mak \ - etc/c/recls/linux.mak - ALLSRCS = $(SRC) $(SRC_STD) $(SRC_STD_C) $(SRC_TI) $(SRC_INT) $(SRC_STD_WIN) \ $(SRC_STD_C_WIN) $(SRC_STD_C_LINUX) $(SRC_ETC) $(SRC_ETC_C) \ - $(SRC_ZLIB) $(SRC_GC) \ - $(SRC_RECLS) $(SRC_STLSOFT) - + $(SRC_ZLIB) $(SRC_GC) #libphobos.a : $(OBJS) internal/gc/dmgc.a linux.mak libphobos.a : $(OBJS) internal/gc/dmgc.a $(ZLIB_OBJS) $(RECLS_OBJS) linux.mak @@ -369,12 +202,6 @@ # cd ../.. make -C ./internal/gc -f linux.mak dmgc.a -$(RECLS_OBJS): -# cd etc/c/recls -# make -f linux.mak -# cd ../../.. - make -C ./etc/c/recls -f linux.mak - $(ZLIB_OBJS): # cd etc/c/zlib # make -f linux.mak @@ -438,9 +265,6 @@ llmath.o : internal/llmath.d $(DMD) -c $(DFLAGS) internal/llmath.d -match.o : internal/match.d - $(DMD) -c $(DFLAGS) internal/match.d - memset.o : internal/memset.d $(DMD) -c $(DFLAGS) internal/memset.d @@ -485,9 +309,6 @@ conv.o : std/conv.d $(DMD) -c $(DFLAGS) std/conv.d -cover.o : std/cover.d - $(DMD) -c $(DFLAGS) std/cover.d - cstream.o : std/cstream.d $(DMD) -c $(DFLAGS) std/cstream.d @@ -500,6 +321,9 @@ dateparse.o : std/dateparse.d std/date.d $(DMD) -c $(DFLAGS) std/dateparse.d +disposable.o : std/disposable.d + $(DMD) -c $(DFLAGS) std/disposable.d + demangle.o : std/demangle.d $(DMD) -c $(DFLAGS) std/demangle.d Binary files phobos-original-2006-02-22/recls.o and phobos-disposable-2006-02-22/recls.o differ diff -rNu phobos-original-2006-02-22/std/disposable.d phobos-disposable-2006-02-22/std/disposable.d --- phobos-original-2006-02-22/std/disposable.d 1969-12-31 18:00:00.000000000 -0600 +++ phobos-disposable-2006-02-22/std/disposable.d 2006-02-22 22:50:11.000000000 -0600 @@ -0,0 +1,201 @@ +module std.disposable; + +private import object; +private import std.c.stdio; +private import std.c.stdlib; +private import std.string; + +version (linux) private import std.c.linux.linux; + +extern (C) void _STI_monitor_staticctor(); +extern (C) void _STD_monitor_staticdtor(); +extern (C) void _STI_critical_init(); +extern (C) void _STD_critical_term(); +extern (C) void gc_init(); +extern (C) void gc_term(); +extern (C) void _minit(); +extern (C) void _moduleCtor(); +extern (C) void _moduleDtor(); +extern (C) void _moduleUnitTests(); + +// Result of call to D main function: +int mainResult = 0; +char[]* _dmain2_am; + +// Interface for Disposable objects to inherit from +public interface Disposable { + // This is the Dispose() method that gets called when the object is + // to be disposed. + public void Dispose(); +} + +/* Guaranteed disposal of Disposable objects: */ +private Disposable[] disposableObjects; + +version (linux) { + extern (C) { + alias int pid_t; + + // daemon functions: + pid_t fork(); + int umask(int); + int setsid(); + int close(int fd); + + // Signal trapping in Linux: + typedef void (*sighandler_t)(int); + sighandler_t signal(int signum, sighandler_t handler); + + // C function signal handler: + void sighandler(int sig) { + char[] signame; + + switch (sig) { + case SIGHUP: signame = "SIGHUP"; break; + case SIGINT: signame = "SIGINT"; break; + case SIGQUIT: signame = "SIGQUIT"; break; + case SIGILL: signame = "SIGILL"; break; + case SIGTRAP: signame = "SIGTRAP"; break; + case SIGABRT: signame = "SIGABRT"; break; + case SIGBUS: signame = "SIGBUS"; break; + case SIGFPE: signame = "SIGFPE"; break; + case SIGKILL: signame = "SIGKILL"; break; + case SIGUSR1: signame = "SIGUSR1"; break; + case SIGSEGV: signame = "SIGSEGV"; break; + case SIGUSR2: signame = "SIGUSR2"; break; + case SIGPIPE: signame = "SIGPIPE"; break; + case SIGALRM: signame = "SIGALRM"; break; + case SIGTERM: signame = "SIGTERM"; break; + case SIGSTKFLT: signame = "SIGSTKFLT"; break; + case SIGCHLD: signame = "SIGCHLD"; break; + case SIGCONT: signame = "SIGCONT"; break; + case SIGSTOP: signame = "SIGSTOP"; break; + case SIGTSTP: signame = "SIGTSTP"; break; + case SIGTTIN: signame = "SIGTTIN"; break; + case SIGTTOU: signame = "SIGTTOU"; break; + case SIGURG: signame = "SIGURG"; break; + case SIGXCPU: signame = "SIGXCPU"; break; + case SIGXFSZ: signame = "SIGXFSZ"; break; + case SIGVTALRM: signame = "SIGVTALRM"; break; + case SIGPROF: signame = "SIGPROF"; break; + case SIGWINCH: signame = "SIGWINCH"; break; + case SIGPOLL: signame = "SIGPOLL"; break; + case SIGPWR: signame = "SIGPWR"; break; + case SIGSYS: signame = "SIGSYS"; break; + default: signame = "unknown"; break; + } + printf("Signal %.*s caught!\n", signame, sig); + + // First, dispose all marked Disposable objects: + while (_disposeObjects()) { } + // Last, terminate as phobos would: + _phobosTerminate(); + } + } +} + +// Dispose a marked Disposable object. +// Reentrant function for maximum protection from failure. +bool _disposeObjects() { + // This loop is critical; we must always at least TRY to dispose each object. + // Failure of one is not an excuse to not dispose all others. + + // NOTE: Unfortunately, a signal generated from a Dispose method is + // fatal to the process, and will not recover and attempt to dispose other objects. + + if (disposableObjects.length > 0) { + // Pop first item off the list: + Disposable obj = disposableObjects[0]; + disposableObjects = disposableObjects[1 .. $]; + + // TODO: Perform other checks here? + if (obj is null) { + printf("*"); + return true; + } + + // Try to dispose the object + try { + obj.Dispose(); + printf("."); + return true; + } catch (Object o) { + // If failed, print the exception and move on... + printf("Error while disposing an object at %p: ", obj); + o.print(); + return false; + } + } else { + return false; + } +} + +// Phobos termination procedure: +void _phobosTerminate() { + try { + _moduleDtor(); + gc_term(); + } catch (Object o) { + printf("Error: "); + o.print(); + exit(EXIT_FAILURE); + } + + version (linux) + { + free(_dmain2_am); + _STD_critical_term(); + _STD_monitor_staticdtor(); + } + exit(mainResult); +} + +void setupForDisposal() { + version (linux) + { + signal(SIGABRT, &sighandler); + signal(SIGTERM, &sighandler); + signal(SIGQUIT, &sighandler); + signal(SIGINT, &sighandler); + signal(SIGKILL, &sighandler); + signal(SIGSEGV, &sighandler); + signal(SIGFPE, &sighandler); + } + version (Win32) + { + // To be done... + } +} + +// User class calls this to mark the object for disposal. Without this, +// the Dispose() method will NOT be called. +public void markForDisposal(Disposable obj) { + // TODO: check distinctness of disposable objects. + disposableObjects ~= obj; +} + +// User class calls this to unmark an object for disposal. +// After this, the Dispose() method will NOT be called on program termination. + +// TODO: This could be much more efficient... +public void unmarkForDisposal(Disposable obj) { + foreach (int i, Disposable chk; disposableObjects) { + if (chk is obj) { + disposableObjects = disposableObjects[0 .. i] ~ disposableObjects[i + 1 .. $]; + return; + } + } +} + +// Call to check if an object is marked for disposal upon program +// termination. + +// TODO: This could be much more efficient... +public bool isMarkedForDisposal(Disposable obj) { + foreach (int i, Disposable chk; disposableObjects) { + if (chk is obj) { + return true; + } + } + return false; +}