You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Ivan Pedruzzi (Jira)" <ji...@apache.org> on 2022/09/02 21:03:00 UTC

[jira] [Created] (DAEMON-447) Allow to rotate stdout and stderr redirected logs

Ivan Pedruzzi created DAEMON-447:
------------------------------------

             Summary: Allow to rotate stdout and stderr redirected logs 
                 Key: DAEMON-447
                 URL: https://issues.apache.org/jira/browse/DAEMON-447
             Project: Commons Daemon
          Issue Type: Improvement
          Components: prunsrv
    Affects Versions: 1.3.1, 1.3.0
         Environment: Windows 10; WIndows Server  2016
            Reporter: Ivan Pedruzzi


We have a large legacy web application which makes use of System.out.println to print errors.  

Our Tomcat 9 is configured to redirect stdout to file using switch --StdOut

In some peculiar conditions our web application can print a very large amount error which end up in the log file and can quickly fill the hard drive, crashing the system.  

Looking at the code in prunsrv.c  it is possible to implement a simple rotation policy which would limit the size of the log from stdout to a configurable number of bytes.

Piggy backing on the worker thread "eventThread", when the log file size is above a configurable threshold (new option  StdOutFileMaxSize) we could make a copy of the log and truncate the file.   

To enable the rotation for the redirects, we would need 2 options:

--Rotate <Interval in seconds for checking the file size>
--StdOutFileMaxSize <Max number of bytes for the log file size>  



These could be used for both stderr and stdout or split in dedicated options

 

Here is the worked altered with my change. In my local tests it behaves as I expect.  

DWORD WINAPI eventThread(LPVOID lpParam)
{
    DWORD dwRotateCnt = SO_LOGROTATE;

    for (;;) {
        DWORD dw = WaitForSingleObject(gSignalEvent, 1000);
        if (dw == WAIT_TIMEOUT) {
            /* Do process maintenance */
            if (SO_LOGROTATE != 0 && --dwRotateCnt == 0) {
                /* Perform log rotation. */
               
              /* START CHANGE */ 
        
                __int64 MAX_Mbytes = SO_STDOUTFILEMAXSIZE;
                struct _stat64 fileInfo;
                if (gStdwrap.szStdOutFilename 
                    && gStdwrap.fpStdOutFile
                    && _fstat64(_fileno(gStdwrap.fpStdOutFile), &fileInfo) == 0
                    && fileInfo.st_size > MAX_Mbytes) {

                    WCHAR sPath[SIZ_PATHLEN];
                    lstrlcpyW(sPath, MAX_PATH, gStdwrap.szStdOutFilename);
                    lstrlcatW(sPath, SIZ_PATHMAX, L"-backup.log");

                    //Make a copy of current log before truncating it
                    CopyFileW(gStdwrap.szStdOutFilename, sPath, FALSE);

                    //close current handle 
                    fclose(gStdwrap.fpStdOutFile);

                    //re-open file to truncate it
                    FILE* tempHandle = _wfsopen(gStdwrap.szStdOutFilename, L"w", _SH_DENYNO);
                    fclose(tempHandle);
                    
                    //re-open in append mode
                    gStdwrap.fpStdOutFile = _wfsopen(gStdwrap.szStdOutFilename, L"a", _SH_DENYNO);
                    _dup2(_fileno(gStdwrap.fpStdOutFile), 1);
                    *stdout = *(gStdwrap.fpStdOutFile);
                 }

                 /* END CHANGE */ 


                 dwRotateCnt = SO_LOGROTATE;
            }
            continue;
        }
        if (dw == WAIT_OBJECT_0 && gSignalValid) {
            if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0)) {
                /* Invoke Thread dump */
                if (gWorker && _jni_startup)
                    apxJavaDumpAllStacks(gWorker);
            }
            ResetEvent(gSignalEvent);
            continue;
        }
        break;
    }
    ExitThread(0);
    return 0;
    UNREFERENCED_PARAMETER(lpParam);
}

   

 

 

 

 

 

 

 

 

 

 

 

 



--
This message was sent by Atlassian Jira
(v8.20.10#820010)