Merge pull request #11828 from gustavotrott/pdf-conv-timeout

Make timeout configurable and log timeout errors for conversions (Pdf2Svg and Office2Pdf)
This commit is contained in:
Anton Georgiev 2021-04-05 11:54:53 -04:00 committed by GitHub
commit 63554b33c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 86 additions and 39 deletions

View File

@ -89,4 +89,9 @@ public abstract class AbstractCommandHandler extends
public Boolean isCommandSuccessful() {
return !exitedWithError();
}
public Boolean isCommandTimeout() {
return exitCode == 124;
}
}

View File

@ -59,18 +59,22 @@ public abstract class Office2PdfPageConverter {
log.info(String.format("Calling conversion script %s.", presOfficeConversionExec));
NuProcessBuilder officeConverterExec = new NuProcessBuilder(Arrays.asList(presOfficeConversionExec, presentationFile.getAbsolutePath(), output.getAbsolutePath()));
NuProcessBuilder officeConverterExec = new NuProcessBuilder(Arrays.asList("timeout", conversionTimeout + "s", "/bin/sh", "-c",
"\""+presOfficeConversionExec + "\" \"" + presentationFile.getAbsolutePath() + "\" \"" + output.getAbsolutePath()+"\""));
Office2PdfConverterHandler office2PdfConverterHandler = new Office2PdfConverterHandler();
officeConverterExec.setProcessListener(office2PdfConverterHandler);
NuProcess process = officeConverterExec.start();
try {
process.waitFor(conversionTimeout, TimeUnit.SECONDS);
process.waitFor(conversionTimeout + 1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("InterruptedException while counting PDF pages {}", presentationFile.getName(), e);
}
if(office2PdfConverterHandler.isCommandTimeout()) {
log.error("Command execution ({}) exceeded the {} secs timeout for {}.",presOfficeConversionExec, conversionTimeout, presentationFile.getName());
}
if(!office2PdfConverterHandler.isCommandSuccessful()) {
throw new Exception(String.format("Error while executing conversion script %s.", presOfficeConversionExec));
}

View File

@ -29,8 +29,7 @@ public class SvgImageCreatorImp implements SvgImageCreator {
private SwfSlidesGenerationProgressNotifier notifier;
private long imageTagThreshold;
private long pathsThreshold;
private String convTimeout = "60s";
private int WAIT_FOR_SEC = 60;
private int convPdfToSvgTimeout = 60;
private String BLANK_SVG;
@Override
@ -64,20 +63,24 @@ public class SvgImageCreatorImp implements SvgImageCreator {
dest = imagePresentationDir.getAbsolutePath() + File.separator + "slide-1.pdf";
NuProcessBuilder convertImgToSvg = new NuProcessBuilder(
Arrays.asList("timeout", convTimeout, "convert", source, "-auto-orient", dest));
Arrays.asList("timeout", convPdfToSvgTimeout + "s", "convert", source, "-auto-orient", dest));
Png2SvgConversionHandler pHandler = new Png2SvgConversionHandler();
convertImgToSvg.setProcessListener(pHandler);
NuProcess process = convertImgToSvg.start();
try {
process.waitFor(WAIT_FOR_SEC, TimeUnit.SECONDS);
process.waitFor(convPdfToSvgTimeout + 1, TimeUnit.SECONDS);
done = true;
} catch (InterruptedException e) {
done = false;
log.error("InterruptedException while converting to SVG {}", dest, e);
}
if(pHandler.isCommandTimeout()) {
log.error("Command execution (convertImgToSvg) exceeded the {} secs timeout for {} page {}.", convPdfToSvgTimeout, pres.getName(), page);
}
// Use the intermediate PDF file as source
source = dest;
}
@ -97,12 +100,16 @@ public class SvgImageCreatorImp implements SvgImageCreator {
NuProcess process = convertPdfToSvg.start();
try {
process.waitFor(WAIT_FOR_SEC, TimeUnit.SECONDS);
process.waitFor(convPdfToSvgTimeout + 1, TimeUnit.SECONDS);
done = true;
} catch (InterruptedException e) {
log.error("Interrupted Exception while generating SVG slides {}", pres.getName(), e);
}
if(pHandler.isCommandTimeout()) {
log.error("Command execution (convertPdfToSvg) exceeded the {} secs timeout for {} page {}.", convPdfToSvgTimeout, pres.getName(), page);
}
if (!done) {
return done;
}
@ -159,47 +166,67 @@ public class SvgImageCreatorImp implements SvgImageCreator {
convertPdfToPng.setProcessListener(pngHandler);
NuProcess pngProcess = convertPdfToPng.start();
try {
pngProcess.waitFor(WAIT_FOR_SEC, TimeUnit.SECONDS);
pngProcess.waitFor(convPdfToSvgTimeout + 1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("Interrupted Exception while generating PNG image {}", pres.getName(), e);
}
// Step 2: Convert a PNG image to SVG
NuProcessBuilder convertPngToSvg = new NuProcessBuilder(Arrays.asList("timeout", convTimeout, "convert",
tempPng.getAbsolutePath(), destsvg.getAbsolutePath()));
Png2SvgConversionHandler svgHandler = new Png2SvgConversionHandler();
convertPngToSvg.setProcessListener(svgHandler);
NuProcess svgProcess = convertPngToSvg.start();
try {
svgProcess.waitFor(WAIT_FOR_SEC, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("Interrupted Exception while generating SVG image {}", pres.getName(), e);
if(pngHandler.isCommandTimeout()) {
log.error("Command execution (convertPdfToPng) exceeded the {} secs timeout for {} page {}.", convPdfToSvgTimeout, pres.getName(), page);
}
done = svgHandler.isCommandSuccessful();
if(tempPng.length() > 0) {
// Step 2: Convert a PNG image to SVG
NuProcessBuilder convertPngToSvg = new NuProcessBuilder(Arrays.asList("timeout", convPdfToSvgTimeout + "s", "convert",
tempPng.getAbsolutePath(), destsvg.getAbsolutePath()));
Png2SvgConversionHandler svgHandler = new Png2SvgConversionHandler();
convertPngToSvg.setProcessListener(svgHandler);
NuProcess svgProcess = convertPngToSvg.start();
try {
svgProcess.waitFor(convPdfToSvgTimeout + 1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("Interrupted Exception while generating SVG image {}", pres.getName(), e);
}
if(svgHandler.isCommandTimeout()) {
log.error("Command execution (convertPngToSvg) exceeded the {} secs timeout for {} page {}.", convPdfToSvgTimeout, pres.getName(), page);
}
done = svgHandler.isCommandSuccessful();
if(destsvg.length() > 0) {
// Step 3: Add SVG namespace to the destionation file
// Check : https://phabricator.wikimedia.org/T43174
NuProcessBuilder addNameSpaceToSVG = new NuProcessBuilder(Arrays.asList("timeout", convPdfToSvgTimeout + "s",
"/bin/sh", "-c",
"sed -i "
+ "'4s|>| xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.2\">|' "
+ destsvg.getAbsolutePath()));
AddNamespaceToSvgHandler namespaceHandler = new AddNamespaceToSvgHandler();
addNameSpaceToSVG.setProcessListener(namespaceHandler);
NuProcess namespaceProcess = addNameSpaceToSVG.start();
try {
namespaceProcess.waitFor(convPdfToSvgTimeout + 1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("Interrupted Exception while adding SVG namespace {}", pres.getName(), e);
}
if (namespaceHandler.isCommandTimeout()) {
log.error("Command execution (addNameSpaceToSVG) exceeded the {} secs timeout for {} page {}.", convPdfToSvgTimeout, pres.getName(), page);
}
}
}
// Delete the temporary PNG after finishing the image conversion
tempPng.delete();
// Step 3: Add SVG namespace to the destionation file
// Check : https://phabricator.wikimedia.org/T43174
NuProcessBuilder addNameSpaceToSVG = new NuProcessBuilder(Arrays.asList("timeout", convTimeout,
"/bin/sh", "-c",
"sed -i "
+ "'4s|>| xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.2\">|' "
+ destsvg.getAbsolutePath()));
AddNamespaceToSvgHandler namespaceHandler = new AddNamespaceToSvgHandler();
addNameSpaceToSVG.setProcessListener(namespaceHandler);
NuProcess namespaceProcess = addNameSpaceToSVG.start();
try {
namespaceProcess.waitFor(WAIT_FOR_SEC, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("Interrupted Exception while adding SVG namespace {}", pres.getName(), e);
if(tempPng.exists()) {
tempPng.delete();
}
}
long endConv = System.currentTimeMillis();
//System.out.println("******** CREATING SVG page " + page + " " + (endConv - startConv));
@ -232,7 +259,7 @@ public class SvgImageCreatorImp implements SvgImageCreator {
rawCommand += " && cat " + destFile;
rawCommand += " | egrep 'data:image/png;base64|<path' | sed 's/ / /g' | cut -d' ' -f 1 | sort | uniq -cw 2";
}
return new NuProcessBuilder(Arrays.asList("timeout", convTimeout, "/bin/sh", "-c", rawCommand));
return new NuProcessBuilder(Arrays.asList("timeout", convPdfToSvgTimeout + "s", "/bin/sh", "-c", rawCommand));
}
private File determineSvgImagesDirectory(File presentationFile) {
@ -278,4 +305,9 @@ public class SvgImageCreatorImp implements SvgImageCreator {
SwfSlidesGenerationProgressNotifier notifier) {
this.notifier = notifier;
}
public void setConvPdfToSvgTimeout(int convPdfToSvgTimeout) {
this.convPdfToSvgTimeout = convPdfToSvgTimeout;
}
}

View File

@ -98,6 +98,11 @@ numConversionThreads=5
#------------------------------------
numFileProcessorThreads=2
#------------------------------------
# Timeout(secs) to wait for pdf to svg conversion (timeout for each tool called during the process)
#------------------------------------
svgConversionTimeout=60
#------------------------------------
# Timeout(secs) to wait for conversion script execution
#------------------------------------

View File

@ -86,6 +86,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<property name="imageTagThreshold" value="${imageTagThreshold}"/>
<property name="pathsThreshold" value="${placementsThreshold}"/>
<property name="blankSvg" value="${BLANK_SVG}"/>
<property name="convPdfToSvgTimeout" value="${svgConversionTimeout}"/>
</bean>
<bean id="generatedSlidesInfoHelper" class="org.bigbluebutton.presentation.GeneratedSlidesInfoHelperImp"/>