1

Main context

We're actually trying to get a multi-threading version of Ghostscript x64 DLL, to make use of it through Ghostscript .NET. This component is supposed to "allow runing multiple Ghostscript instances simultaneously within a single process", but, as we have checked in our project, works fine until concurrent requests are made to the application. Same behavior can be replicated lauching same method using Tasks. The error description that raises in both cases, just when a call to the process is made until the last is being executed, is:

An error occured when call to 'gsapi_new_instance' is made: -100

Even it does no seem to be related with .NET directly, I will post a sample of our C# method code, just for contextualize.

// Define switches...
string[] switchesArray = switches.ToArray();

using (GhostscriptProcessor procesador = new GhostscriptProcessor())
{
    try
    {
        procesador.StartProcessing(switchesArray, null);

        byte[] destinationFile = System.IO.File.ReadAllBytes(destinationPath);

        return destinationFile;

    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        System.IO.File.Delete(sourceFile);
    }
}

THREADSAFE solution

Starting our investigation, we found this KenS's answer on this post, indicating that Ghostscript DLL must be generated with GS_THREADSAFE compiler definition.

To clarify, as we make use of Ghostscript 9.52 x64 to generate our PDFs, we need this x64 DLL compiled for Release configuration. After trying to compile Ghostscript sources on Windows 10 x64 machine, using Visual Studio Community 2017 and Visual Studio Community 2019, we finally managed to build and generate all items (only with VS Community 2019) without GS_THREADSAFE parameter, just to confirm that compilation is fine, and we check that the DLLs and executables are working. For this process we took in mind all we found in Ghostscript official documentation.

As we have no other guide to include this GS_THREADSAFE parameter, we followed the instructions given in this solution, including XCFLAGS="-DGS_THREADSAFE=1" on nmake build commands, usign this sentence for Rebuild all option:

cd .. && nmake -f psi\msvc32.mak WIN64= SBR=1 DEVSTUDIO= XCFLAGS=-DGS_THREADSAFE=1 && nmake -f psi\msvc32.mak WIN64= DEVSTUDIO= XCFLAGS=-DGS_THREADSAFE=1 bsc

This approach, rises an error during build:

Error LNK2019 unresolved external symbol errprintf_nomem referenced in function gs_log_error File \mkromfs.obj 1

As it seems, the file mkromfs.c has a method called errprintf_nomem, which can't be found when GS_THREADSAFE is set.

Questions

1 - Is there any public release of Ghostscript that include x64 DLLs compiled to be THREADSAFE?

And, if not (that's what I'm guessing...)

2 - Is it possible to get this DLL to be THREADSAFE without changing the source code?

3- Could anyone provide, please, a step by step guide or walkthrough to build a x64 Ghostscript DLL using GS_THREADSAFE using Visual Studio (or even any other possible alternative) over Windows 10 x64?

4 - A few posts talk about people achive to manage multithreading using Ghostscript .NET. I assume this examples are all using a GS_THREADSAFE DLL... Is any other workaround we have passed?

Thank a lot in advance.

Dave Miller
  • 536
  • 3
  • 19
  • I’m voting to close this question because this is not a programming question, its technical support for Ghostscript. – KenS Sep 15 '20 at 15:18
  • 2
    Take a look at this example: https://github.com/jhabjan/Ghostscript.NET/blob/master/Ghostscript.NET.Samples/Samples/RunMultipleInstancesSample.cs This approach tells Ghostscript.NET to load each ghostscript dll instance into it's own memory space and therefore allow multiple instances running at a same time. – HABJAN Sep 16 '20 at 15:38
  • 1
    Thank you very much, Josip. We must have overlooked this step before. Including a custom class for ConsoleStdIo, and adding a new instance of this class to the code line of the Processor, as it's represented on the sample, works like a charm. Still waiting try this on a more challenging environment, but the first load tests we made with this approach left hopeful results. Please, state this as a reply, and I will be happy to mark this as an answer, as this solved all my problem. Hopefully, the post was not closed, and the answer has a programming solution, which, for us, is very significant. – Dave Miller Sep 17 '20 at 11:25

2 Answers2

1

To summarize all this questions, and as a guide for future developers having this same trouble, these are the answers we've found until now:

  1. AS @KenS mentions in his reply: "No, the Ghostscript developers don't actually build thread-safe versions of the binaries."

  2. At this very moment, clearly not, as it has been reported on this opened bug.

  3. As it seems to be a matter of commercial licensing support, we avoid comment on this point anymore.

  4. Thanks again to @HABJAN. I absolutely take back what I've stated on my question, as it is possible to have Ghostscript .NET working on multi-threading scenarios. Below comes the solution we applied, in case it could be useful for someone.

Based on HABJAN example, what we have done to achieve this was to create a custom class to capture Ghostscript logging:

protected class ConsoleStdIO : Ghostscript.NET.GhostscriptStdIO
{
    public ConsoleStdIO(bool handleStdIn, bool handleStdOut, bool handleStdErr) : base(handleStdIn, handleStdOut, handleStdErr)
    {
    }

    public override void StdIn(out string input, int count)
    {
        char[] userInput = new char[count];
        Console.In.ReadBlock(userInput, 0, count);
        input = new string(userInput);
    }

    public override void StdOut(string output)
    {
        //log
    }

    public override void StdError(string error)
    {
        //log
    }
}

For our previous method, we simple include a call to this class and this avoids errors when multiple tasks are executed at the same time:

// Define switches...
string[] switchesArray = switches.ToArray();

using (GhostscriptProcessor procesador = new GhostscriptProcessor())
{
    try
    {
        procesador.StartProcessing(switchesArray, new ConsoleStdIO(true, true, true));

        byte[] destinationFile = System.IO.File.ReadAllBytes(destinationPath);

        return destinationFile;

    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        System.IO.File.Delete(sourceFile);
    }
}
Dave Miller
  • 536
  • 3
  • 19
-1

Well, it seems to me that you are asking here for technical support.

You clearly want to use Ghostscript in a commercial undertaking, indeed one might reasonably say you want an enterprise version of Ghostscript. Presumably you don't want to alter the source in order to permit you to use an open source license, because you don't want to pay for a commercial license.

With that in mind the answers to your questions are:

  1. No, the Ghostscript developers don't actually build thread-safe versions of the binaries.
  2. Currently, no. That's probably an oversight.
  3. That would be a technical support question, there's no guarantee of technical support to free users, it's the one of the few areas of leverage for dual license vendors to persuade people to take up a commercial license. So I hope you will understand that I'm not going to provide that.
  4. as far as I can see, no.
halfer
  • 19,824
  • 17
  • 99
  • 186
KenS
  • 30,202
  • 3
  • 34
  • 51
  • Thanks for your answer, Ken. Until this moment, we tried Ghostscript in our solution and we exposed our plan and context to Artifex, to ensure in fact that we could avoid getting a commercial license (that was confirmed by the commercial departament). As far as we can see, we do not change our approach, just simply we do wish to use it on a multi-threading context (as it would be embedded in a web application, this point was explained to Artifex). – Dave Miller Sep 16 '20 at 06:54
  • After reading Ghostscript licensing documentation and transfer the license query to Artifex, we do not know that having a multi-threading version of the DLL required a commercial license, so we simply just make our way to understand why the DLL doesn't work on concurrence scenarios, and the investigation lead us to that point, just asking for knowledge and information. If this case is suppose to be observed from a commercial perspective, as we do require technnical support from Artifex to achieve this, of course, I truly understand this information could not be provided to us for free, really. – Dave Miller Sep 16 '20 at 06:54
  • This is a personal point of view, but maybe it should be advisable that Ghostscript clearly state in the licesing documentacion that if you plan to use Ghostscript through a web application with mutithreading capabilities you require to modify source code (involving all requirements, such as relase you own source code, concerning to AGPL license), or even ask for a commecial license. That should spare time of research and help future users to understand fully the alternatives they have in such cases. – Dave Miller Sep 16 '20 at 06:54
  • See my comment on point 2, "that's probably an oversight". You could open a bug report.... – KenS Sep 16 '20 at 07:03
  • Yes, we already made it. Once we have an answer, we'll contact Artifex commercial departament again to review the case again or even consider other aletrnatives, that will enventually involve to change the documentation provider. – Dave Miller Sep 16 '20 at 11:17