diff --git a/library/changes b/library/changes index 20bb0a4..2c54e86 100644 --- a/library/changes +++ b/library/changes @@ -136,6 +136,9 @@ file handles from concurrent use which SystemTagList() might just end up using. +- Activated the dormant thread-safe standard input/output/error + handling code. + c.lib 1.189 (5.3.2005) diff --git a/library/stdio_fdhookentry.c b/library/stdio_fdhookentry.c index fa31f57..cf08846 100644 --- a/library/stdio_fdhookentry.c +++ b/library/stdio_fdhookentry.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_fdhookentry.c,v 1.23 2005-03-18 12:38:23 obarthel Exp $ + * $Id: stdio_fdhookentry.c,v 1.24 2005-03-24 16:40:16 obarthel Exp $ * * :ts=4 * @@ -76,33 +76,52 @@ __fd_hook_entry( file = fd->fd_DefaultFile; - /* Check if this file should be dynamically bound to one of the - three standard I/O streams. */ - if(file == ZERO && FLAG_IS_SET(fd->fd_Flags,FDF_STDIO)) + #if defined(__THREAD_SAFE) { - if (fd == __fd[STDIN_FILENO]) + /* Check if this file should be dynamically bound to one of the + three standard I/O streams. */ + if(file == ZERO && FLAG_IS_SET(fd->fd_Flags,FDF_STDIO)) { - file = Input(); - } - else if (__num_fd > STDOUT_FILENO && fd == __fd[STDOUT_FILENO]) - { - file = Output(); - } - else if (__num_fd > STDERR_FILENO && fd == __fd[STDERR_FILENO]) - { - #if defined(__amigaos4__) + /* We assume that the file descriptors are organized in the + default layout, i.e. 0 = stdin, 1 = stdout, 2 = stderr. + It might be that the table does not hold more than one + entry, though, hence the __num_fd checks prior to + accessing the table entries. The first test is really + redundant since there has to be at least one file + descriptor table entry around or this function would + not have been invoked in the first place. */ + if (/*__num_fd > STDIN_FILENO &&*/ fd == __fd[STDIN_FILENO]) { - file = ErrorOutput(); + file = Input(); } - #else + else if (__num_fd > STDOUT_FILENO && fd == __fd[STDOUT_FILENO]) { - struct Process * this_process = (struct Process *)FindTask(NULL); + file = Output(); + } + else if (__num_fd > STDERR_FILENO && fd == __fd[STDERR_FILENO]) + { + #if defined(__amigaos4__) + { + file = ErrorOutput(); + } + #else + { + struct Process * this_process = (struct Process *)FindTask(NULL); - file = this_process->pr_CES; + file = this_process->pr_CES; + } + #endif /* __amigaos4__ */ + + /* The following is rather controversial; if the standard error stream + is unavailable, we default to reuse the standard output stream. This + is problematic if the standard output stream was redirected and should + not be the same as the standard error output stream. */ + if(file == ZERO) + file = Output(); } - #endif /* __amigaos4__ */ } } + #endif /* __THREAD_SAFE */ if(file == ZERO) { diff --git a/library/stdio_file_init.c b/library/stdio_file_init.c index ffffc00..1372afa 100644 --- a/library/stdio_file_init.c +++ b/library/stdio_file_init.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_file_init.c,v 1.6 2005-03-18 12:38:23 obarthel Exp $ + * $Id: stdio_file_init.c,v 1.7 2005-03-24 16:40:16 obarthel Exp $ * * :ts=4 * @@ -273,25 +273,32 @@ FILE_CONSTRUCTOR(stdio_file_init) goto out; } + + /* We ignore the file handle and let the file I/O code + in the fd hook pick up the appropriate Input/Output/ErrorOutput + handle. */ + default_file = ZERO; + + fd_flags |= FDF_NO_CLOSE | FDF_STDIO; } #else { stdio_lock = NULL; fd_lock = NULL; + + /* Check if this stream is attached to a console window. */ + if(default_file != ZERO) + { + PROFILE_OFF(); + + if(IsInteractive(default_file)) + SET_FLAG(fd_flags,FDF_IS_INTERACTIVE); + + PROFILE_ON(); + } } #endif /* __THREAD_SAFE */ - /* Check if this stream is attached to a console window. */ - if(default_file != ZERO) - { - PROFILE_OFF(); - - if(IsInteractive(default_file)) - SET_FLAG(fd_flags,FDF_IS_INTERACTIVE); - - PROFILE_ON(); - } - /* Align the buffer start address to a cache line boundary. */ aligned_buffer = (char *)((ULONG)(buffer + (CACHE_LINE_SIZE-1)) & ~(CACHE_LINE_SIZE-1)); @@ -306,62 +313,66 @@ FILE_CONSTRUCTOR(stdio_file_init) stdio_lock); } - /* If the program was launched from Workbench, we continue by - duplicating the default output stream for use as the - standard error stream. */ - if(__WBenchMsg != NULL) + #if NOT defined(__THREAD_SAFE) { - PROFILE_OFF(); - __fd[STDERR_FILENO]->fd_DefaultFile = Output(); - PROFILE_ON(); - - SET_FLAG(__fd[STDERR_FILENO]->fd_Flags,FDF_NO_CLOSE); - } - else - { - BPTR ces; - - PROFILE_OFF(); - - /* Figure out what the default error output stream is. */ - #if defined(__amigaos4__) + /* If the program was launched from Workbench, we continue by + duplicating the default output stream for use as the + standard error stream. */ + if(__WBenchMsg != NULL) { - ces = ErrorOutput(); - } - #else - { - struct Process * this_process = (struct Process *)FindTask(NULL); - - ces = this_process->pr_CES; - } - #endif /* __amigaos4__ */ - - PROFILE_ON(); - - /* Is the standard error stream configured? If so, use it. - Otherwise, try to duplicate the standard output stream. */ - if(ces != ZERO) - { - __fd[STDERR_FILENO]->fd_DefaultFile = ces; + PROFILE_OFF(); + __fd[STDERR_FILENO]->fd_DefaultFile = Output(); + PROFILE_ON(); SET_FLAG(__fd[STDERR_FILENO]->fd_Flags,FDF_NO_CLOSE); } else { - __fd[STDERR_FILENO]->fd_DefaultFile = Open("CONSOLE:",MODE_NEWFILE); + BPTR ces; + + PROFILE_OFF(); + + /* Figure out what the default error output stream is. */ + #if defined(__amigaos4__) + { + ces = ErrorOutput(); + } + #else + { + struct Process * this_process = (struct Process *)FindTask(NULL); + + ces = this_process->pr_CES; + } + #endif /* __amigaos4__ */ + + PROFILE_ON(); + + /* Is the standard error stream configured? If so, use it. + Otherwise, try to duplicate the standard output stream. */ + if(ces != ZERO) + { + __fd[STDERR_FILENO]->fd_DefaultFile = ces; + + SET_FLAG(__fd[STDERR_FILENO]->fd_Flags,FDF_NO_CLOSE); + } + else + { + __fd[STDERR_FILENO]->fd_DefaultFile = Open("CONSOLE:",MODE_NEWFILE); + } } + + PROFILE_OFF(); + + /* Figure out if the standard error stream is bound to a console. */ + if(__fd[STDERR_FILENO]->fd_DefaultFile != ZERO) + { + if(IsInteractive(__fd[STDERR_FILENO]->fd_DefaultFile)) + SET_FLAG(__fd[STDERR_FILENO]->fd_Flags,FDF_IS_INTERACTIVE); + } + + PROFILE_ON(); } - - PROFILE_OFF(); - - /* Figure out if the standard error stream is bound to a console. */ - if(__fd[STDERR_FILENO]->fd_DefaultFile != ZERO) - { - if(IsInteractive(__fd[STDERR_FILENO]->fd_DefaultFile)) - SET_FLAG(__fd[STDERR_FILENO]->fd_Flags,FDF_IS_INTERACTIVE); - } - - PROFILE_ON(); + #endif /* __THREAD_SAFE */ success = TRUE;