Changeset 3669 for trunk


Ignore:
Timestamp:
Feb 22, 2025, 2:31:14 AM (5 months ago)
Author:
bird
Message:

kmk: More stdout close error debugging

Location:
trunk/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/Makefile.kmk

    r3666 r3669  
    243243kmk_DEFS.win       := CONFIG_WITH_OUTPUT_IN_MEMORY
    244244kmk_DEFS.win.x86   := CONFIG_NEW_WIN32_CTRL_EVENT
    245 kmk_DEFS.win.amd64 := CONFIG_NEW_WIN32_CTRL_EVENT DEBUG_STDOUT_CLOSE_ISSUE
     245kmk_DEFS.win.amd64 := CONFIG_NEW_WIN32_CTRL_EVENT
    246246kmk_DEFS.debug     := CONFIG_WITH_MAKE_STATS
    247247ifdef CONFIG_WITH_MAKE_STATS
     
    313313endif
    314314
     315kmk_DEFS.win    += DEBUG_STDOUT_CLOSE_ISSUE
     316kmk_SOURCES.win += ../lib/msc_buffered_printf.c
     317
    315318kmk_DEFS.freebsd.x86 = CONFIG_WITHOUT_THREADS
    316319
  • trunk/src/kmk/output.c

    r3666 r3669  
    1515this program.  If not, see <http://www.gnu.org/licenses/>.  */
    1616
     17#if defined (DEBUG_STDOUT_CLOSE_ISSUE) && defined (KBUILD_OS_WINDOWS)
     18# include "nt/ntstuff.h"
     19# include "nt/nthlp.h"
     20# include <process.h>
     21#endif
    1722#include "makeint.h"
    1823#include "job.h"
     
    6166
    6267#ifdef DEBUG_STDOUT_CLOSE_ISSUE
     68
    6369/* fflush wrapper w/ error checking + reporting for stdout.
    6470   This is to debug the mysterious 'kmk: write error: stdout' errors. */
    6571int g_fStdOutError = 0;
     72
     73# ifdef KBUILD_OS_WINDOWS
     74static void my_output_pipe_info (HANDLE hStdOut, const char *pszWhere)
     75{
     76  MY_IO_STATUS_BLOCK Ios = {0} ;
     77  struct MY_FILE_PIPE_INFORMATION
     78  {
     79      ULONG           ReadMode;
     80      ULONG           CompletionMode;
     81  } Info1 = {0};
     82  MY_NTSTATUS rcNt1 = g_pfnNtQueryInformationFile(hStdOut, &Ios, &Info1, sizeof(Info1), MyFilePipeInformation);
     83  struct MY_FILE_PIPE_LOCAL_INFORMATION
     84  {
     85      ULONG           NamedPipeType;
     86      ULONG           NamedPipeConfiguration;
     87      ULONG           MaximumInstances;
     88      ULONG           CurrentInstances;
     89      ULONG           InboundQuota;
     90      ULONG           ReadDataAvailable;
     91      ULONG           OutboundQuota;
     92      ULONG           WriteQuotaAvailable;
     93      ULONG           NamedPipeState;
     94      ULONG           NamedPipeEnd;
     95  } Info2 = {0};
     96  MY_NTSTATUS rcNt2 = g_pfnNtQueryInformationFile(hStdOut, &Ios, &Info2, sizeof(Info2), MyFilePipeLocalInformation);
     97  union { BYTE ab[1024]; MY_FILE_NAME_INFORMATION NameInfo; } uBuf = {{0}};
     98  MY_NTSTATUS rcNt3 = g_pfnNtQueryInformationFile(hStdOut, &Ios, &uBuf, sizeof(uBuf) - sizeof(WCHAR), MyFileNameInformation);
     99  fprintf(stderr, "kmk[%u/%u]: stdout pipeinfo at %s: mode=%#x complmode=%#x type=%#x cfg=%#x instances=%u/%u inquota=%#x readable=%#x outquota=%#x writable=%#x state=%#x end=%#x hStdOut=%p %S rcNt=%#x/%#x/%#x\n",
     100          makelevel, _getpid(), pszWhere, Info1.ReadMode, Info1.CompletionMode, Info2.NamedPipeType, Info2.NamedPipeConfiguration,
     101          Info2.CurrentInstances, Info2.MaximumInstances, Info2.InboundQuota, Info2.ReadDataAvailable, Info2.OutboundQuota,
     102          Info2.WriteQuotaAvailable, Info2.NamedPipeState, Info2.NamedPipeEnd,
     103          hStdOut, uBuf.NameInfo.FileName, rcNt1, rcNt2, rcNt3);
     104}
     105# endif /* KBUILD_OS_WINDOWS */
    66106
    67107static void my_stdout_error (const char *pszOperation, const char *pszMessage)
     
    75115  HANDLE    const hNative = (HANDLE)_get_osfhandle (_fileno (stdout));
    76116  DWORD const     dwType  = GetFileType (hNative);
    77   fprintf (stderr, "kmk[%u]: %s: %s! (lasterr=%u errno=%d fileno=%d native=%p type=%#x)\n",
    78            makelevel, pszOperation, pszMessage, dwErr, iErrNo, fdFile, hNative, dwType);
     117  unsigned int    uDosErr = _doserrno;
     118  if ((dwType & ~FILE_TYPE_REMOTE) == FILE_TYPE_PIPE)
     119    my_output_pipe_info (hNative, "error");
     120  fprintf (stderr, "kmk[%u/%u]: stdout error: %s: %s! (lasterr=%u errno=%d fileno=%d uDosErr=%u native=%p type=%#x)\n",
     121           makelevel, _getpid(), pszOperation, pszMessage, dwErr, iErrNo, fdFile, uDosErr, hNative, dwType);
    79122# else
    80   fprintf (stderr, "kmk[%u]: %s: %s! (lasterr=%u errno=%d fileno=%d)\n",
     123  fprintf (stderr, "kmk[%u]: stdout error: %s: %s! (lasterr=%u errno=%d fileno=%d)\n",
    81124           makelevel, pszOperation, pszMessage, dwErr, iErrNo, fdFile);
    82125# endif
    83126}
    84127
     128/* Preserves errno and win32 last error. */
     129void my_check_stdout (const char *pszWhere)
     130{
     131  if (!g_fStdOutError)
     132    {
     133# ifdef KBUILD_OS_WINDOWS
     134      DWORD const dwErrSaved  = GetLastError();
     135# endif
     136      int const   iErrNoSaved = errno;
     137
     138      if (ferror (stdout))
     139        {
     140          my_stdout_error (pszWhere, "error pending!");
     141          g_fStdOutError = 1;
     142        }
     143
     144      errno = iErrNoSaved;
     145# ifdef KBUILD_OS_WINDOWS
     146      SetLastError(dwErrSaved);
     147# endif
     148    }
     149}
     150
     151# ifdef KBUILD_OS_WINDOWS
     152/* generic fwrite wrapper */
     153__declspec(dllexport) size_t __cdecl fwrite(void const *pvBuf, size_t cbItem, size_t cItems, FILE *pFile)
     154{
     155  size_t cbWritten;
     156  if (pFile == stdout)
     157    my_check_stdout("fwrite/entry");
     158  _lock_file(pFile);
     159  cbWritten = _fwrite_nolock(pvBuf, cbItem, cItems, pFile);
     160  _unlock_file(pFile);
     161  if (pFile == stdout)
     162    my_check_stdout("fwrite/exit");
     163  return cbWritten;
     164}
     165void * const __imp_fwrite  = (void *)(uintptr_t)fwrite;
     166
     167/* generic fflush wrapper */
     168__declspec(dllexport) int __cdecl fflush(FILE *pFile)
     169{
     170  int rc;
     171  if (pFile == stdout || !pFile)
     172    my_check_stdout("fflush/entry");
     173  if (pFile)
     174    {
     175      _lock_file(pFile);
     176      rc = _fflush_nolock(pFile);
     177      _unlock_file(pFile);
     178    }
     179  if (pFile == stdout || !pFile)
     180    my_check_stdout("fflush/exit");
     181  return rc;
     182}
     183void * const __imp_fflush  = (void *)(uintptr_t)fflush;
     184
     185# else
    85186static int my_fflush (FILE *pFile)
    86187{
     
    110211}
    111212
    112 # undef  fflush
    113 # define fflush(a_pFile) my_fflush(a_pFile)
    114 
    115 /* Preserves errno and win32 last error. */
    116 void my_check_stdout (const char *pszWhere)
    117 {
    118   if (!g_fStdOutError)
    119     {
    120 # ifdef KBUILD_OS_WINDOWS
    121       DWORD const dwErrSaved  = GetLastError();
    122 # endif
    123       int const   iErrNoSaved = errno;
    124 
    125       if (ferror (stdout))
    126         {
    127           my_stdout_error (pszWhere, "error pending!");
    128           g_fStdOutError = 1;
    129         }
    130 
    131       errno = iErrNoSaved;
    132 # ifdef KBUILD_OS_WINDOWS
    133       SetLastError(dwErrSaved);
    134 # endif
    135     }
    136 }
     213#  undef  fflush
     214#  define fflush(a_pFile) my_fflush(a_pFile)
     215# endif
    137216
    138217#endif /* DEBUG_STDOUT_CLOSE_ISSUE */
     
    12801359  if (ferror (stdout))
    12811360    my_stdout_error ("output_init", "error pending on exit!");
     1361# ifdef KBUILD_OS_WINDOWS
     1362  {
     1363    HANDLE const hStdOut = (HANDLE)_get_osfhandle(_fileno(stdout));
     1364    DWORD const  dwType  = GetFileType(hStdOut);
     1365    birdResolveImportsWorker();
     1366    if ((dwType & ~FILE_TYPE_REMOTE) == FILE_TYPE_PIPE)
     1367      {
     1368        my_output_pipe_info (hStdOut, "output_init");
     1369#  if 0
     1370        DWORD cbOutBuf      = 0;
     1371        DWORD cbInBuf       = 0;
     1372        BOOL const fRc2 = GetNamedPipeInfo(hStdOut, NULL, &cbOutBuf, &cbInBuf, NULL);
     1373        if (cbInBuf != 0x1000)
     1374          {
     1375            DWORD dwMode = 0;
     1376            if (GetNamedPipeHandleStateW(hStdOut, &dwMode, NULL, NULL, NULL, NULL, 0))
     1377              {
     1378                dwMode &= ~PIPE_WAIT;
     1379                dwMode |= PIPE_NOWAIT;
     1380                if (!SetNamedPipeHandleState(hStdOut, &dwMode, NULL, NULL))
     1381                  fprintf(stderr, "SetNamedPipeHandleState failed: %u\n", GetLastError());
     1382                else
     1383                  {
     1384                    GetNamedPipeHandleStateW(hStdOut, &dwMode, NULL, NULL, NULL, NULL, 0);
     1385                    fprintf(stderr, "SetNamedPipeHandleState succeeded: %#x\n", dwMode);
     1386                  }
     1387              }
     1388          }
     1389#  endif
     1390# endif
     1391      }
     1392    }
    12821393#endif
    12831394#ifdef HAVE_ATEXIT
  • trunk/src/lib/msc_buffered_printf.c

    r3661 r3669  
    123123     * Fallback.
    124124     */
     125# ifdef DEBUG_STDOUT_CLOSE_ISSUE
     126    extern void my_check_stdout(const char *pszWhere);
     127    if (pFile == stdout)
     128        my_check_stdout("__stdio_common_vfprintf/entry");
     129    int rcRet = g_pfnFallback_vfprintf(fOptions, pFile, pszFormat, hLocale, va);
     130    if (pFile == stdout)
     131        my_check_stdout("__stdio_common_vfprintf/exit");
     132    return rcRet;
     133# else
    125134    return g_pfnFallback_vfprintf(fOptions, pFile, pszFormat, hLocale, va);
     135# endif
    126136}
    127137
Note: See TracChangeset for help on using the changeset viewer.