Running several instances of headless libreoffice: where's race?

I’m running libreoffice (headless) to make several hundreds of pdfs from odts. It’s too slow, so I’ve tried to run some in parallel.

SOME pdf files are generated without any error but with zero size. Running one libreoffice at a time, I never hit it; running two, often.

I’ve tried to run it as recommended with custom UserInstallation and in separate directories like

/usr/local/lib/libreoffice/program/soffice.bin "-env:UserInstallation=file:///tmp/oo.44978" --headless --convert-to pdf /tmp/oo.44978/046rEQ1Nee.odt --outdir /tmp/oo.44978

Which resulted in 100% corruption.

I’ve even tried to use different sockets

/usr/local/lib/libreoffice/program/soffice.bin --nofirststartwizard --accept="socket,host=127.0.0.1,port=53668;urp;" "-env:UserInstallation=file:///tmp/oo.53668" --headless --convert-to pdf /tmp/oo.53668/xaKag8N_3d.odt --outdir /tmp/oo.53668

With the same result

-env:SingleAppInstance=“false” did not help as well

Where’s a race condition in libreoffice and how do I evade it?

LibreOffice 7.6.4.1 if that’s matter.

FreeBSD 13.2-RELEASE if that’s matter.

SingleAppInstance isn’t a LibreOffice environment variable. It is a switch controlling Portable Apps launcher. It seems that advises on sites related to LibreOffice, where the switch origin isn’t explained, have created some cargo cult. Indeed, this switch will never work in -env: agrument, which is only effective inside the soffice process, so doesn’t affect any wrappers.

Please clarify. You say first, that some method of running two instances of LibreOffice process gives you the problem sometimes (often); and that using the recommended method, it gives you the problem in 100% of cases? Is that a correct reading of your wording? If so, then what is the method that gives the problem sometimes?

Running 10 soffices in parallel, I got about half files corrupted, others processed. I think it’s because of instances of soffice starts less synchronous and sometimes miss the race point.

So we are only discussing one method of parallel run. OK.

It’s your guess. When you run LibreOffice with different profiles, they are 100% separate, then there would be no race between them. I’d first check your hardware (e.g., failing RAM), to exclude the possibility that under an increased load, you get hit by the failure that isn’t reached when running a single instance.

They run with common profile, so that’s not the profile problem. I still have no idea where do they race. Shared memory mayb?..

Yes, is possible run several instances. In this example execute four instances. Only change port argument.

soffice -env:UserInstallation=file:///tmp/LIBO_Process8103 --headless --norestore --nologo --accept='socket,host=localhost,port=8103;urp;StarOffice.ComponentContext'

foro

 /usr/local/lib/libreoffice/program/soffice.bin --accept="socket,host=127.0.0.1,port=52534;urp;StarOffice.ComponentContext" -env:UserInstallation="file:///tmp/oo.32534" --headless --norestore --convert-to pdf /tmp/oo.32534/kzSvhAGyBt.odt --outdir /tmp/oo.32534
/usr/local/lib/libreoffice/program/soffice.bin --accept="socket,host=127.0.0.1,port=52533;urp;StarOffice.ComponentContext" -env:UserInstallation="file:///tmp/oo.32533" --headless --norestore --convert-to pdf /tmp/oo.32533/r3wMyhyWV5.odt --outdir /tmp/oo.32533

running in parallel results in two zero-sized pdf files. Running sequental, works fine.

What’s odd is that I don’t see “convert /tmp/oo.32533/r3wMyhyWV5.odt as a Writer document → /tmp/oo.32533/r3wMyhyWV5.pdf using filter : writer_pdf_Export” in parallel run.

The first emphasized quote (“in parallel”) contradicts the second one (“They run with common profile”). Exactly because to make several LibreOffice processes run in parallel, you must use different profiles. It’s not the command line parameter "-env:UserInstallation" does some magic; it is the user profile directory defines a unique identifier, and all LibreOffice instances try to find an already started instance using the same profile; if they find one, they pass their workload to that first process, wait for it to be processed there, and exit (so when you use the same user profile, either implicitly - without any command line switch - or explicitly, you don’t get a parallel processing).

Now if you are using the same profile, and you try to run processes in parallel (i.e., several processes using that same profile are started with their --convert-to switches, running several at the same moment, as opposed to a script that starts the next task after the previous ended), then the following might - and definitely sometimes will - happen:

  1. Process a starts, with its conversion defined by its --convert-to switch
  2. Process a defines a system pipe with the name based on the profile path, so that following processes can discover it
  3. Process a starts doing its task
  4. Process b starts, with its different conversion defined by its --convert-to switch
  5. Process b tries to open the pipe based on the profile path; that succeeds
  6. Process a ends processing its work
  7. Process b sends its command line to process a
  8. Process a exits, because its --convert-to is a “do its job, then exit” kind of command.

When you use the same profile, you must use a single always-running instance (started without a --convert-to parameter), and then all instances that you later start with --convert-to will send their jobs to that central not-exiting instance. Not only that will be safe; it will also work much faster, because there will be no startup/shutdown penalty that you pay per each process (note that majority of that penalty happens not because of OS starting a process, but because LibreOffice initializes / deinitializes itself).

When you run several parallel jobs, you must use different profiles. But then you may use a poor strategy of several scripts, each handling part of the whole list of files, using its profile, and calling LibreOffice for the files one by one (this will have the same startup/shutdown penalty); or you may again start several instances (one per profile) first, without --convert-to, and then call --convert-to instances that will sent their command lines to those parallel permanent instances. Or - you may build several huge command lines, each listing all the files that each instance must process, and then start separate parallel tasks, each with its own huge command line. That way, they will start once, process all their files, and shutdown, without a fear that some other process will try to interfere.

2 Likes

So to process several templates in parallel I should better

  1. Create some profiles
  2. Run headless soffices with different ports
  3. Run convert-to in proper profiles, so they’d pass job to long-running instances

?

Okay, looks interesting.

  1. After some research, I’ve got 100% reproduceable error.

With NO /tmp/oo.* directories,

/usr/local/lib/libreoffice/program/soffice.bin --accept="socket,host=127.0.0.1,port=42358;urp;StarOffice.ComponentContext" -env:UserInstallation="file:///tmp/oo.22358" --headless --norestore --convert-to pdf /tmp/PTpU1WJOhI.odt --outdir /tmp  & /usr/local/lib/libreoffice/program/soffice.bin --accept="socket,host=127.0.0.1,port=42359;urp;StarOffice.ComponentContext" -env:UserInstallation="file:///tmp/oo.22359" --headless --norestore --convert-to pdf /tmp/AUq04mceY3.odt --outdir /tmp

suddenly resulted in error 81 on both instances.

error 81 is an EXITHELPER_NORMAL_RESTART - “just restart me”.

/usr/local/lib/libreoffice/program/soffice.bin --headless --norestore --convert-to pdf /tmp/PTpU1WJOhI.odt --outdir /tmp & /usr/local/lib/libreoffice/program/soffice.bin --headless --norestore --convert-to pdf /tmp/AUq04mceY3.odt --outdir /tmp

resulted in exactly one (first) pdf being created, the process exits with exit code 1, second runs ok without ever opening odt file.

Attempt to run a headless instance in advance works, but it exits right after conversion, so it’s barely reusable.

Clearly there’s a race condition, but where? Okay, for now I’ll just try to run soffice twice…