VirtualBox

Changeset 95903 in vbox for trunk/src/VBox/Runtime/r3


Ignore:
Timestamp:
Jul 28, 2022 11:56:03 AM (2 years ago)
Author:
vboxsync
Message:

IPRT/stream: Flush & cleanup of non-standard streams on exit/unload like regular crt does (IIRC). bugref:10261

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/stream.cpp

    r95894 r95903  
    6868#ifdef RTSTREAM_STANDALONE
    6969# include <iprt/file.h>
     70# include <iprt/list.h>
    7071#endif
    7172#include <iprt/mem.h>
     73#ifdef RTSTREAM_STANDALONE
     74# include <iprt/once.h>
     75#endif
    7276#include <iprt/param.h>
    7377#include <iprt/string.h>
     
    175179    PRTCRITSECT         pCritSect;
    176180#endif
     181#ifdef RTSTREAM_STANDALONE
     182    /** Entry in g_StreamList (for automatic flushing and closing at
     183     * exit/unload). */
     184    RTLISTNODE          ListEntry;
     185#endif
    177186} RTSTREAM;
    178187
     
    221230    /* .fRecheckMode = */       true,
    222231#ifndef HAVE_FWRITE_UNLOCKED
    223     /* .pCritSect = */          NULL
     232    /* .pCritSect = */          NULL,
     233#endif
     234#ifdef RTSTREAM_STANDALONE
     235    /* .ListEntry = */          { NULL, NULL },
    224236#endif
    225237};
     
    249261    /* .fRecheckMode = */       true,
    250262#ifndef HAVE_FWRITE_UNLOCKED
    251     /* .pCritSect = */          NULL
     263    /* .pCritSect = */          NULL,
     264#endif
     265#ifdef RTSTREAM_STANDALONE
     266    /* .ListEntry = */          { NULL, NULL },
    252267#endif
    253268};
     
    277292    /* .fRecheckMode = */       true,
    278293#ifndef HAVE_FWRITE_UNLOCKED
    279     /* .pCritSect = */          NULL
     294    /* .pCritSect = */          NULL,
     295#endif
     296#ifdef RTSTREAM_STANDALONE
     297    /* .ListEntry = */          { NULL, NULL },
    280298#endif
    281299};
     
    289307/** Pointer to the standard output stream. */
    290308RTDATADECL(PRTSTREAM)   g_pStdOut = &g_StdOut;
     309
     310#ifdef RTSTREAM_STANDALONE
     311/** Run-once initializer for the stream list (g_StreamList + g_StreamListCritSect). */
     312static RTONCE           g_StreamListOnce = RTONCE_INITIALIZER;
     313/** List of user created streams (excludes the standard streams). */
     314static RTLISTANCHOR     g_StreamList;
     315/** Critical section protecting the stream list. */
     316static RTCRITSECT       g_StreamListCritSect;
     317
     318
     319/** @callback_method_impl{FNRTONCE}   */
     320static DECLCALLBACK(int32_t) rtStrmListInitOnce(void *pvUser)
     321{
     322    RT_NOREF(pvUser);
     323    RTListInit(&g_StreamList);
     324    return RTCritSectInit(&g_StreamListCritSect);
     325}
     326
     327#endif
    291328
    292329
     
    442479        return VINF_SUCCESS;
    443480    }
     481
     482#ifdef RTSTREAM_STANDALONE
     483    /*
     484     * Make the the stream list is initialized before we allocate anything.
     485     */
     486    int rc2 = RTOnce(&g_StreamListOnce, rtStrmListInitOnce, NULL);
     487    AssertRCReturn(rc2, rc2);
     488#endif
    444489
    445490    /*
     
    480525        if (RT_SUCCESS(rc))
    481526        {
     527#ifdef RTSTREAM_STANDALONE
     528            /* We keep a list of these for cleanup purposes. */
     529            RTCritSectEnter(&g_StreamListCritSect);
     530            RTListAppend(&g_StreamList, &pStream->ListEntry);
     531            RTCritSectLeave(&g_StreamListCritSect);
     532#endif
    482533            *ppStream = pStream;
    483534            return VINF_SUCCESS;
     
    559610     * Invalidate the stream and destroy the critical section first.
    560611     */
     612#ifdef RTSTREAM_STANDALONE
     613    RTCritSectEnter(&g_StreamListCritSect);
     614    RTListNodeRemove(&pStream->ListEntry);
     615    RTCritSectLeave(&g_StreamListCritSect);
     616#endif
    561617    pStream->u32Magic = 0xdeaddead;
    562618#ifndef HAVE_FWRITE_UNLOCKED
     
    12951351
    12961352/**
    1297  * Worker for rtStrmFlushAndCloseAll.
    1298  */
    1299 static void rtStrmFlushAndClose(PRTSTREAM pStream, bool fStaticStream)
    1300 {
    1301     if (!fStaticStream)
    1302         pStream->u32Magic = ~RTSTREAM_MAGIC;
    1303 
     1353 * Worker for rtStrmFlushAndCloseAll and rtStrmFlushAndClose.
     1354 */
     1355static RTFILE rtStrmFlushAndCleanup(PRTSTREAM pStream)
     1356{
    13041357    if (pStream->pchBuf)
    13051358    {
     
    13151368
    13161369    PRTCRITSECT pCritSect = pStream->pCritSect;
    1317     pStream->pCritSect = NULL;
    13181370    if (pCritSect)
    13191371    {
     1372        pStream->pCritSect = NULL;
    13201373        RTCritSectDelete(pCritSect);
    13211374        RTMemFree(pCritSect);
    13221375    }
    13231376
    1324     if (pStream->hFile != NIL_RTFILE)
    1325     {
    1326         if (!fStaticStream)
    1327             RTFileClose(pStream->hFile);
    1328         /* else: no structure or memory behind RTFILE yet, so okay to just drop it. */
    1329         pStream->hFile = NIL_RTFILE;
    1330     }
    1331 
    1332     if (!fStaticStream)
    1333         RTMemFree(pStream);
     1377    RTFILE hFile = pStream->hFile;
     1378    pStream->hFile = NIL_RTFILE;
     1379    return hFile;
     1380}
     1381
     1382
     1383/**
     1384 * Worker for rtStrmFlushAndCloseAll.
     1385 */
     1386static void rtStrmFlushAndClose(PRTSTREAM pStream)
     1387{
     1388    pStream->u32Magic = ~RTSTREAM_MAGIC;
     1389    RTFILE hFile = rtStrmFlushAndCleanup(pStream);
     1390    if (hFile != NIL_RTFILE)
     1391        RTFileClose(hFile);
     1392    RTMemFree(pStream);
    13341393}
    13351394
     
    13441403     * Flush the standard handles.
    13451404     */
    1346     rtStrmFlushAndClose(&g_StdOut, true);
    1347     rtStrmFlushAndClose(&g_StdErr, true);
    1348     rtStrmFlushAndClose(&g_StdIn,  true);
     1405    rtStrmFlushAndCleanup(&g_StdOut);
     1406    rtStrmFlushAndCleanup(&g_StdErr);
     1407    rtStrmFlushAndCleanup(&g_StdIn);
    13491408
    13501409    /*
    13511410     * Make a list of the rest and flush+close those too.
    13521411     */
    1353     /** @todo */
     1412    if (RTOnceWasInitialized(&g_StreamListOnce))
     1413    {
     1414        RTCritSectDelete(&g_StreamListCritSect);
     1415
     1416        PRTSTREAM pStream;
     1417        while ((pStream = RTListRemoveFirst(&g_StreamList, RTSTREAM, ListEntry)) != NULL)
     1418            rtStrmFlushAndClose(pStream);
     1419
     1420        RTOnceReset(&g_StreamListOnce);
     1421    }
    13541422}
    13551423
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette