Benjamin De Boe created UIMA-4899:
-------------------------------------

             Summary: UIMACPP access violation when running in multiple threads
                 Key: UIMA-4899
                 URL: https://issues.apache.org/jira/browse/UIMA-4899
             Project: UIMA
          Issue Type: Bug
          Components: C++ Framework
    Affects Versions: 2.8.1SDK
         Environment: Windows 10 64bit
            Reporter: Benjamin De Boe


When running a bunch of threads accessing separate AE instances of the UIMACPP 
DaveDetector in JNI mode, the process crashes with an access violation on the 
call to "delete pInstance" in destructorJNI in jni/jni.cpp.

The code below should allow you to reproduce the issue and takes three 
command-line arguments:
1: the full path to DaveDescriptor.xml
2: whether to use simple threads ("n") or separate processes ("y")
3: (optional, default 20) size of the CAS pool to use, which we found out has 
an impact in reproducing the issue.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.intersys.uima.test;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import org.apache.uima.UIMAFramework;
import org.apache.uima.analysis_engine.AnalysisEngine;
import org.apache.uima.cas.CAS;
import org.apache.uima.resource.ResourceSpecifier;
import org.apache.uima.util.CasCreationUtils;
import org.apache.uima.util.CasPool;
import org.apache.uima.util.Level;
import org.apache.uima.util.XMLInputSource;

/**
 *
 * @author bdeboe
 */
public class Standalone implements Runnable {

    private String text;
    private AnalysisEngine ae;
    private CasPool pool;

    public Standalone(String txt, AnalysisEngine ae, CasPool pool) {
        this.text = txt;
        this.ae = ae;
        this.pool = pool;
    }

    public static void main(String[] args) throws Exception {

        String descPath = ((args != null) && (args.length > 0)) ? args[0] : 
"C:\\InterSystems\\UIMA\\bin\\DaveDetector.xml";
 
        if ((args != null) && (args.length > 1) && (args[1].charAt(0) == 'y')) {
            async(descPath);
            return;
        }
        
       int casPoolSize = ((args != null) && (args.length > 2)) ? 
Integer.valueOf(args[2]) : 20;

        XMLInputSource in = new XMLInputSource(descPath);
        ResourceSpecifier specifier
                = UIMAFramework.getXMLParser().parseResourceSpecifier(in);
        AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(specifier);

        CasPool pool = (casPoolSize > 0) ? new CasPool(casPoolSize, ae) : null;
        String loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing 
elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut 
enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip 
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate 
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat 
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est 
laborum.";
        for (int i = 0; i < 25; i++) {
            Standalone task = new Standalone(loremIpsum, 
UIMAFramework.produceAnalysisEngine(specifier), (casPoolSize > 0) ? pool : 
null);
            Thread t = new Thread(task);
            t.start();
        }
    }

    public static int async(String descriptor) throws Exception {
        String javaHome = System.getProperty("java.home");
        String javaBin = javaHome
                + File.separator + "bin"
                + File.separator + "java";
        //String classpath = System.getProperty("java.class.path");
        URL[] urls = ((URLClassLoader) 
Thread.currentThread().getContextClassLoader()).getURLs();
        StringBuilder classPath = new StringBuilder();
        for (URL url : urls) {
            classPath.append(url.getPath()).append(";");
        }
        System.out.println(javaBin.concat(" -cp 
").concat(classPath.toString()).concat(" 
").concat(Standalone.class.getCanonicalName()).concat(" ").concat(descriptor));
        ProcessBuilder builder = new ProcessBuilder(
                javaBin, "-cp", classPath.toString(), 
Standalone.class.getCanonicalName(), descriptor);
        builder.redirectErrorStream(true);
        builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
        Process[] processes = new Process[4];
        processes[0] = builder.start();
        processes[1] = builder.start();
        processes[2] = builder.start();
        processes[3] = builder.start();
        int done = 0;
        do {
            Thread.sleep(1000);
            done = 0;
            for (int i = 0; i < 4; i++) {
                if (!processes[i].isAlive()) {
                    done++;
                }
            }
            System.out.println(String.valueOf(done).concat(" processes done"));
        } while (done < 4);

        return processes[3].exitValue();
    }

    @Override
    public void run() {

        CAS cas  = null;
        try {
            if (pool != null) { 
                cas = pool.getCas();
            } else {
                cas = 
CasCreationUtils.createCas(ae.getAnalysisEngineMetaData());
            }

            UIMAFramework.getLogger().log(Level.WARNING, "created CAS in thread 
".concat(String.valueOf(Thread.currentThread().getId())));
            cas.setDocumentText(text);
            ae.process(cas);
            
            System.out.println("Done processing text");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (pool != null) pool.releaseCas(cas);
        }
    }
}




--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to