Investigating Memory Leak in LibreOffice Headless Conversion

I am using LibreOffice version 24.2.5.2 420(Build:2) in headless mode to convert Word files to PDF. I execute the command from my Node.js server using "soffice --headless --convert-to pdf "${filePath}" --outdir "${outputDir}" for the request I receive, which contains the file.

I have a Node.js server which listens for POST requests containing Word documents. When a valid file is uploaded, it saves the document, converts it to PDF using LibreOffice in headless mode, and then streams the resulting PDF back to the client while deleting the temporary files afterward.

And am running this in a Docker container (Ubuntu base image).

While using this setup, I noticed a memory leak in LibreOffice.

I have a shell script that I used to test the issue by continuously making API calls to the Node.js server for one hour as a single user.

I’ve attached images from my tests, which show that the memory usage does not decrease afterward.

Total requests made: 3182

If this isn’t the right forum for such questions, please direct me to the appropriate location.

Thank you for your time !!!

https://bugs.documentfoundation.org/

How to Report Bugs in LibreOffice - The Document Foundation Wiki

Is an instance of LibreOffice running continuously when you test, or is this command line creating a new instance each time, which processes its request and shuts down, after which, there’s no soffice.bin processes until new request arrives?

I am creating a new instance each time, which processes its request and shuts down soffice.bin

This is how I am running soffice in my node js server

exec(`soffice  --headless --convert-to pdf "${filePath}" --outdir "${outdir}"`, (err) => {
// Error handling
})

Here are the details :

But that means, that that can’t be a problem in LibreOffice, since the memory can’t be leaked from a closed process.

Thanks for the reply
And yep that should be it, but I have observed there are other ghost process left behind after done with the cmd

this is my server code

const http = require('http');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');

const PORT = 3000;

const server = http.createServer((req, res) => {
    if (req.method === 'POST' && req.headers['content-type'] === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
        const time = Date.now() 
        const k = `uploaded${time}`
        const filePath = path.join(__dirname, `${k}.docx`);


        const writeStream = fs.createWriteStream(filePath, {});
        req.pipe(writeStream);

        req.on('end', () => {
            const pdfPath = path.join(__dirname,`${k}.pdf`);

            const paa= path.join(__dirname)


            exec(`soffice  --headless --convert-to pdf "${filePath}" --outdir "${paa}"`, (err) => {
                if (err) {
                    console.error('Error during conversion:', err);
                    res.writeHead(500, { 'Content-Type': 'text/plain' });
                    res.end('Conversion failed');
                    return;
                }

                res.writeHead(200, {
                    'Content-Type': 'application/pdf',
                    'Content-Disposition': 'attachment; filename="output.pdf"'
                });

                const readStream = fs.createReadStream(pdfPath);
                readStream.pipe(res);

                readStream.on('end', () => {
                    fs.unlink(filePath, (err) => {
                        if (err) console.error('Error deleting uploaded file:', err);
                    });
                    fs.unlink(pdfPath, (err) => {
                        if (err) console.error('Error deleting output PDF:', err);
                    });
                });
            });
        });

        req.on('error', (err) => {
            console.error('Error during file upload:', err);
            res.writeHead(500, { 'Content-Type': 'text/plain' });
            res.end('Upload failed');
        });
    } else {
        res.writeHead(400, { 'Content-Type': 'text/plain' });
        res.end('Please upload a Word file');
    }
});

server.listen(PORT, () => {
    console.log(`Server running at http://localhost:${PORT}/`);
});

If i just don’t run the soffice , i dont see this memory leak

The ghost processes are likely something caused by operating system or containers or other infrastructure. LibreOffice, when called to --convert-to, just runs, converts, and closes. Everything else is outside. And those ghost processes may be exactly what causes the leak.

Maybe you just don’t close handles to the process correctly … well, I don’t know the specifics - that would be my guess if you used Win32 API.

Thank you for your assistance.
I’m currently running the server on Ubuntu 24.04.1 LTS. Based on your comment, my assumption is that if I replace the soffice command with another command, we can expect to see an increase in memory leak and potentially some zombie processes. ?

That would be my expectation, yes.