Ejemplo n.º 1
0
void ConfusabledataBuilder::build(const char * confusables, int32_t confusablesLen,
               UErrorCode &status) {

    // Convert the user input data from UTF-8 to UChar (UTF-16)
    int32_t inputLen = 0;
    if (U_FAILURE(status)) {
        return;
    }
    u_strFromUTF8(NULL, 0, &inputLen, confusables, confusablesLen, &status);
    if (status != U_BUFFER_OVERFLOW_ERROR) {
        return;
    }
    status = U_ZERO_ERROR;
    fInput = static_cast<UChar *>(uprv_malloc((inputLen+1) * sizeof(UChar)));
    if (fInput == NULL) {
        status = U_MEMORY_ALLOCATION_ERROR;
    }
    u_strFromUTF8(fInput, inputLen+1, NULL, confusables, confusablesLen, &status);


    // Regular Expression to parse a line from Confusables.txt.  The expression will match
    // any line.  What was matched is determined by examining which capture groups have a match.
    //   Capture Group 1:  the source char
    //   Capture Group 2:  the replacement chars
    //   Capture Group 3-6  the table type, SL, SA, ML, or MA
    //   Capture Group 7:  A blank or comment only line.
    //   Capture Group 8:  A syntactically invalid line.  Anything that didn't match before.
    // Example Line from the confusables.txt source file:
    //   "1D702 ;	006E 0329 ;	SL	# MATHEMATICAL ITALIC SMALL ETA ... "
    fParseLine = uregex_openC(
        "(?m)^[ \\t]*([0-9A-Fa-f]+)[ \\t]+;"      // Match the source char
        "[ \\t]*([0-9A-Fa-f]+"                    // Match the replacement char(s)
           "(?:[ \\t]+[0-9A-Fa-f]+)*)[ \\t]*;"    //     (continued)
        "\\s*(?:(SL)|(SA)|(ML)|(MA))"             // Match the table type
        "[ \\t]*(?:#.*?)?$"                       // Match any trailing #comment
        "|^([ \\t]*(?:#.*?)?)$"       // OR match empty lines or lines with only a #comment
        "|^(.*?)$",                   // OR match any line, which catches illegal lines.
        0, NULL, &status);

    // Regular expression for parsing a hex number out of a space-separated list of them.
    //   Capture group 1 gets the number, with spaces removed.
    fParseHexNum = uregex_openC("\\s*([0-9A-F]+)", 0, NULL, &status);

    // Zap any Byte Order Mark at the start of input.  Changing it to a space is benign
    //   given the syntax of the input.
    if (*fInput == 0xfeff) {
        *fInput = 0x20;
    }

    // Parse the input, one line per iteration of this loop.
    uregex_setText(fParseLine, fInput, inputLen, &status);
    while (uregex_findNext(fParseLine, &status)) {
        fLineNum++;
        if (uregex_start(fParseLine, 7, &status) >= 0) {
            // this was a blank or comment line.
            continue;
        }
        if (uregex_start(fParseLine, 8, &status) >= 0) {
            // input file syntax error.
            status = U_PARSE_ERROR;
            return;
        }

        // We have a good input line.  Extract the key character and mapping string, and
        //    put them into the appropriate mapping table.
        UChar32 keyChar = SpoofImpl::ScanHex(fInput, uregex_start(fParseLine, 1, &status),
                          uregex_end(fParseLine, 1, &status), status);

        int32_t mapStringStart = uregex_start(fParseLine, 2, &status);
        int32_t mapStringLength = uregex_end(fParseLine, 2, &status) - mapStringStart;
        uregex_setText(fParseHexNum, &fInput[mapStringStart], mapStringLength, &status);

        UnicodeString  *mapString = new UnicodeString();
        if (mapString == NULL) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return;
        }
        while (uregex_findNext(fParseHexNum, &status)) {
            UChar32 c = SpoofImpl::ScanHex(&fInput[mapStringStart], uregex_start(fParseHexNum, 1, &status),
                                 uregex_end(fParseHexNum, 1, &status), status);
            mapString->append(c);
        }
        U_ASSERT(mapString->length() >= 1);

        // Put the map (value) string into the string pool
        // This a little like a Java intern() - any duplicates will be eliminated.
        SPUString *smapString = stringPool->addString(mapString, status);

        // Add the UChar32 -> string mapping to the appropriate table.
        UHashtable *table = uregex_start(fParseLine, 3, &status) >= 0 ? fSLTable :
                            uregex_start(fParseLine, 4, &status) >= 0 ? fSATable :
                            uregex_start(fParseLine, 5, &status) >= 0 ? fMLTable :
                            uregex_start(fParseLine, 6, &status) >= 0 ? fMATable :
                            NULL;
        U_ASSERT(table != NULL);
        uhash_iput(table, keyChar, smapString, &status);
        fKeySet->add(keyChar);
        if (U_FAILURE(status)) {
            return;
        }
    }

    // Input data is now all parsed and collected.
    // Now create the run-time binary form of the data.
    //
    // This is done in two steps.  First the data is assembled into vectors and strings,
    //   for ease of construction, then the contents of these collections are dumped
    //   into the actual raw-bytes data storage.

    // Build up the string array, and record the index of each string therein
    //  in the (build time only) string pool.
    // Strings of length one are not entered into the strings array.
    // At the same time, build up the string lengths table, which records the
    // position in the string table of the first string of each length >= 4.
    // (Strings in the table are sorted by length)
    stringPool->sort(status);
    fStringTable = new UnicodeString();
    fStringLengthsTable = new UVector(status);
    int32_t previousStringLength = 0;
    int32_t previousStringIndex  = 0;
    int32_t poolSize = stringPool->size();
    int32_t i;
    for (i=0; i<poolSize; i++) {
        SPUString *s = stringPool->getByIndex(i);
        int32_t strLen = s->fStr->length();
        int32_t strIndex = fStringTable->length();
        U_ASSERT(strLen >= previousStringLength);
        if (strLen == 1) {
            // strings of length one do not get an entry in the string table.
            // Keep the single string character itself here, which is the same
            //  convention that is used in the final run-time string table index.
            s->fStrTableIndex = s->fStr->charAt(0);
        } else {
            if ((strLen > previousStringLength) && (previousStringLength >= 4)) {
                fStringLengthsTable->addElement(previousStringIndex, status);
                fStringLengthsTable->addElement(previousStringLength, status);
            }
            s->fStrTableIndex = strIndex;
            fStringTable->append(*(s->fStr));
        }
        previousStringLength = strLen;
        previousStringIndex  = strIndex;
    }
    // Make the final entry to the string lengths table.
    //   (it holds an entry for the _last_ string of each length, so adding the
    //    final one doesn't happen in the main loop because no longer string was encountered.)
    if (previousStringLength >= 4) {
        fStringLengthsTable->addElement(previousStringIndex, status);
        fStringLengthsTable->addElement(previousStringLength, status);
    }

    // Construct the compile-time Key and Value tables
    //
    // For each key code point, check which mapping tables it applies to,
    //   and create the final data for the key & value structures.
    //
    //   The four logical mapping tables are conflated into one combined table.
    //   If multiple logical tables have the same mapping for some key, they
    //     share a single entry in the combined table.
    //   If more than one mapping exists for the same key code point, multiple
    //     entries will be created in the table

    for (int32_t range=0; range<fKeySet->getRangeCount(); range++) {
        // It is an oddity of the UnicodeSet API that simply enumerating the contained
        //   code points requires a nested loop.
        for (UChar32 keyChar=fKeySet->getRangeStart(range);
                keyChar <= fKeySet->getRangeEnd(range); keyChar++) {
            addKeyEntry(keyChar, fSLTable, USPOOF_SL_TABLE_FLAG, status);
            addKeyEntry(keyChar, fSATable, USPOOF_SA_TABLE_FLAG, status);
            addKeyEntry(keyChar, fMLTable, USPOOF_ML_TABLE_FLAG, status);
            addKeyEntry(keyChar, fMATable, USPOOF_MA_TABLE_FLAG, status);
        }
    }

    // Put the assembled data into the flat runtime array
    outputData(status);

    // All of the intermediate allocated data belongs to the ConfusabledataBuilder
    //  object  (this), and is deleted in the destructor.
    return;
}
Ejemplo n.º 2
0
void Command::run()
{
    // Check that the binary path is not empty
    if (binaryPath().trimmed().isEmpty()) {
        emit errorText(tr("Unable to start process, binary is empty"));
        return;
    }

    const unsigned processFlags = unixTerminalDisabled() ?
                unsigned(Utils::SynchronousProcess::UnixTerminalDisabled) :
                unsigned(0);
    const QSharedPointer<QProcess> process = Utils::SynchronousProcess::createProcess(processFlags);
    if (!workingDirectory().isEmpty())
        process->setWorkingDirectory(workingDirectory());

    process->setProcessEnvironment(processEnvironment());

    QByteArray stdOut;
    QByteArray stdErr;
    QString error;

    const int count = d->m_jobs.size();
    int exitCode = -1;
    bool ok = true;
    for (int j = 0; j < count; j++) {
        process->start(binaryPath(), d->m_jobs.at(j).arguments);
        if (!process->waitForStarted()) {
            ok = false;
            error += QString::fromLatin1("Error: \"%1\" could not be started: %2")
                    .arg(binaryPath(), process->errorString());
            break;
        }

        process->closeWriteChannel();
        const int timeOutSeconds = d->m_jobs.at(j).timeout;
        if (!Utils::SynchronousProcess::readDataFromProcess(*process, timeOutSeconds * 1000,
                                                            &stdOut, &stdErr, false)) {
            Utils::SynchronousProcess::stopProcess(*process);
            ok = false;
            error += msgTimeout(timeOutSeconds);
            break;
        }

        error += QString::fromLocal8Bit(stdErr);
        exitCode = process->exitCode();
        switch (reportTerminationMode()) {
        case NoReport:
            break;
        case ReportStdout:
            stdOut += msgTermination(exitCode, binaryPath(), d->m_jobs.at(j).arguments).toUtf8();
            break;
        case ReportStderr:
            error += msgTermination(exitCode, binaryPath(), d->m_jobs.at(j).arguments);
            break;
        }
    }

    // Special hack: Always produce output for diff
    if (ok && stdOut.isEmpty() && d->m_jobs.front().arguments.at(0) == QLatin1String("diff")) {
        stdOut += "No difference to HEAD";
    } else {
        // @TODO: Remove, see below
        if (ok && d->m_jobs.front().arguments.at(0) == QLatin1String("status"))
            removeColorCodes(&stdOut);
    }

    d->m_lastExecSuccess = ok;
    d->m_lastExecExitCode = exitCode;

    if (ok && !stdOut.isEmpty())
        emit outputData(stdOut);

    if (!error.isEmpty())
        emit errorText(error);

    emit finished(ok, exitCode, cookie());
    if (ok)
        emit success(cookie());
    // As it is used asynchronously, we need to delete ourselves
    this->deleteLater();
}
Ejemplo n.º 3
0
void wsserver::onTimer()
{
  outputData();
  clock_fdelay(mClock, 5.); // schedule the next clock
}
Ejemplo n.º 4
0
int main (int argc, char *argv[])
{
    int retVal=0;
    int relaysChanged=0;
    int firstTime=1;
    int lastRelayWriteSec=0;
       
    // Config file thingies 
    int status=0;
    char* eString;
    char *globalConfFile="anitaSoft.config";
    // Log stuff 
    char *progName=basename(argv[0]);
    

    int millisecs=0;
    struct timespec milliWait;
    milliWait.tv_sec=0;


    int lastCal=0;
    time_t rawTime;

    // Setup log 
    setlogmask(LOG_UPTO(LOG_INFO));
    openlog (progName, LOG_PID, ANITA_LOG_FACILITY) ;

    // Set signal handlers 
    signal(SIGUSR1, sigUsr1Handler);
    signal(SIGUSR2, sigUsr2Handler);
    signal(SIGTERM, handleBadSigs);
    signal(SIGINT, handleBadSigs);
    signal(SIGSEGV, handleBadSigs);

    //Dont' wait for children
    signal(SIGCLD, SIG_IGN);     

    //Sort out PID File
    retVal=sortOutPidFile(progName);
    if(retVal!=0) {
      return retVal;
    }


    // Load Config 
    kvpReset () ;
    status = configLoad (globalConfFile,"global") ;


    // Get Calibd output dirs
    if (status == CONFIG_E_OK) {
	hkDiskBitMask=kvpGetInt("hkDiskBitMask",1);

	disableUsb=kvpGetInt("disableUsb",1);
	if(disableUsb)
	    hkDiskBitMask&=~USB_DISK_MASK;
	//	disableNeobrick=kvpGetInt("disableNeobrick",1);
	//	if(disableNeobrick)
	//	    hkDiskBitMask&=~NEOBRICK_DISK_MASK;
	disableHelium2=kvpGetInt("disableHelium2",1);
	if(disableHelium2)
	    hkDiskBitMask&=~HELIUM2_DISK_MASK;
	disableHelium1=kvpGetInt("disableHelium1",1);
	if(disableHelium1)
	    hkDiskBitMask&=~HELIUM1_DISK_MASK;
    }
    else {
	eString=configErrorString (status) ;
	syslog(LOG_ERR,"Error reading %s: %s\n",globalConfFile,eString);
    }

    makeDirectories(CALIBD_STATUS_LINK_DIR);
    makeDirectories(HK_TELEM_DIR);
    makeDirectories(HK_TELEM_LINK_DIR);

    prepWriterStructs();

    //Need to set digital carrier num
    retVal=readConfigFile();
    //Setup acromag
    acromagSetup();
    ip470Setup();

    //Set code values
    autoZeroStruct.code=IP320_AVZ;
    rawDataStruct.code=IP320_RAW;
    calDataStruct.code=IP320_CAL;



    do {
	if(printToScreen) printf("Initializing Calibd\n");
	retVal=readConfigFile();
	relaysChanged=1;
	currentState=PROG_STATE_RUN;
//RJN for Hkd
        ip320Setup();
	millisecs=0;
	lastRelayWriteSec=0;
	while(currentState==PROG_STATE_RUN) {	  
	  time(&rawTime);
	  
	  //Set Relays to correct state
	  if(relaysChanged || firstTime) retVal=setRelays();
	  
	  if(relaysChanged || (rawTime-lastRelayWriteSec)>=relayWritePeriod) {

	    if(printToScreen) {
	      printf("Amplite1 (%d)  Amplite2 (%d)  BZAmpa1 (%d)  BZAmpa2 (%d)  NTUAmpa (%d)\tSB (%d) SSD_5V (%d) SSD_12V (%d) SSD_Shutdown (%d)\n",stateAmplite1,stateAmplite2,stateBZAmpa1,stateBZAmpa2,stateNTUAmpa,stateSB,stateNTUSSD5V,stateNTUSSD12V,stateNTUSSDShutdown);
	    }
	    writeStatus();
	    relaysChanged=0;
	    lastRelayWriteSec=rawTime;
	  }
	    

	  if(firstTime) firstTime=0;
	  
	  

	  
	  if((millisecs % readoutPeriod)==0) {
	    
	    time(&rawTime);		
	    
	    //		printf("Mag Ret: %d\n",retVal);
	    if((rawTime-lastCal)>calibrationPeriod) {
	      ip320Calibrate();
	      outputData(IP320_CAL);
	      outputData(IP320_AVZ);
	      lastCal=rawTime;
	    }
	    ip320Read(0);
	    outputData(IP320_RAW);
	    
	    millisecs=1;
	  }
	    //Just for safety we'll reset the sleep time
	  milliWait.tv_nsec=1000000;
	  nanosleep(&milliWait,NULL);
	  millisecs++;	   	 

	} //End of run loop
    } while(currentState==PROG_STATE_INIT);
    closeHkFilesAndTidy(&hkRawWriter);
    closeHkFilesAndTidy(&hkCalWriter);
    closeHkFilesAndTidy(&calibWriter);
    unlink(CALIBD_PID_FILE);
    syslog(LOG_INFO,"Calibd Terminating");
    return 0;
    
 }
Ejemplo n.º 5
0
int main( int argc, char **argv )
{	
  struct pb_Parameters *params;
  params = pb_ReadParameters(&argc, argv);
  if ((params->inpFiles[0] == NULL) || (params->inpFiles[1] != NULL))
    {
      fprintf(stderr, "Expecting one input filename\n");
      exit(-1);
    }

  int err = 0;
  if(argc != 3)
    err |= 1;
  else {
    char* numend;
    N = strtol(argv[1], &numend, 10);
    if(numend == argv[1])
      err |= 2;
    B = strtol(argv[2], &numend, 10);
    if(numend == argv[2])
      err |= 4;
  }

  if(err)
  {
    fprintf(stderr, "Expecting two integers for N and B\n");
    exit(-1);
  }

  //8*1024*1024;
  int n_bytes = N * B* sizeof(float2);
  int nthreads = T;
  
  struct pb_TimerSet timers;
  pb_InitializeTimerSet(&timers);
  pb_AddSubTimer(&timers, oclOverhead, pb_TimerID_KERNEL);
  pb_SwitchToTimer(&timers, pb_TimerID_COMPUTE);

  float *shared_source =(float *)malloc(n_bytes);  
  float2 *source    = (float2 *)malloc( n_bytes );
  float2 *result    = (float2 *)calloc( N*B, sizeof(float2) );

  inputData(params->inpFiles[0],(float*)source,N*B*2);

  // OpenCL Code 
  cl_int clErrNum;
  pb_Context* pb_context;
  pb_context = pb_InitOpenCLContext(params);
  if (pb_context == NULL) {
    fprintf (stderr, "Error: No OpenCL platform/device can be found."); 
    return -1;
  }

  cl_int clStatus;
  cl_device_id clDevice = (cl_device_id) pb_context->clDeviceId;
  cl_platform_id clPlatform = (cl_platform_id) pb_context->clPlatformId;
  cl_context clContext = (cl_context) pb_context->clContext;
  cl_command_queue clCommandQueue;

  cl_program clProgram;

  cl_kernel fft_kernel;

  cl_mem d_source, d_work; //float2 *d_source, *d_work;
  cl_mem d_shared_source; //float *d_shared_source;

  clCommandQueue = clCreateCommandQueue(clContext, clDevice, CL_QUEUE_PROFILING_ENABLE, &clErrNum);
  OCL_ERRCK_VAR(clErrNum);
  
  pb_SetOpenCL(&clContext, &clCommandQueue);
  pb_SwitchToSubTimer(&timers, oclOverhead, pb_TimerID_KERNEL);

  const char *source_path = "src/opencl_nvidia/fft_kernel.cl";
  char *sourceCode;
  sourceCode = readFile(source_path);
  if (sourceCode == NULL) {
    fprintf(stderr, "Could not load program source of '%s'\n", source_path); exit(1);
  }

  clProgram = clCreateProgramWithSource(clContext, 1, (const char **)&sourceCode, NULL, &clErrNum);
  OCL_ERRCK_VAR(clErrNum);

  free(sourceCode);

  /*
    char compileOptions[1024];
  //                -cl-nv-verbose // Provides register info for NVIDIA devices
  // Set all Macros referenced by kernels
  sprintf(compileOptions, "\
                -D PRESCAN_THREADS=%u\
                -D KB=%u -D UNROLL=%u\
                -D BINS_PER_BLOCK=%u -D BLOCK_X=%u",

                prescanThreads,
                lmemKB, UNROLL,
                bins_per_block, blockX
            ); 
  */
  OCL_ERRCK_RETVAL ( clBuildProgram(clProgram, 1, &clDevice, NULL /*compileOptions*/, NULL, NULL) );


  char *build_log;
  size_t ret_val_size;
  OCL_ERRCK_RETVAL ( clGetProgramBuildInfo(clProgram, clDevice, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size) );
  build_log = (char *)malloc(ret_val_size+1);
  OCL_ERRCK_RETVAL ( clGetProgramBuildInfo(clProgram, clDevice, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL) );

  // to be careful, terminate with \0
  build_log[ret_val_size] = '\0';

  fprintf(stderr, "%s\n", build_log );

  fft_kernel = clCreateKernel(clProgram, "GPU_FftShMem", &clErrNum);
  OCL_ERRCK_VAR(clErrNum);

  pb_SwitchToTimer(&timers, pb_TimerID_COPY);
  // allocate & copy device memory
  d_shared_source = clCreateBuffer(clContext, CL_MEM_COPY_HOST_PTR, n_bytes, shared_source, &clErrNum);  OCL_ERRCK_VAR(clErrNum);

  d_source = clCreateBuffer(clContext, CL_MEM_COPY_HOST_PTR, n_bytes, source, &clErrNum);  OCL_ERRCK_VAR(clErrNum);
  
  //result is initially zero'd out
  d_work = clCreateBuffer(clContext, CL_MEM_COPY_HOST_PTR, n_bytes, result, &clErrNum);  OCL_ERRCK_VAR(clErrNum);

  pb_SwitchToTimer(&timers, pb_TimerID_KERNEL);
  
  size_t block[1] = { nthreads };
  size_t grid[1] = { B*block[0] };
  
  OCL_ERRCK_RETVAL( clSetKernelArg(fft_kernel, 0, sizeof(cl_mem), (void *)&d_source) );
  OCL_ERRCK_RETVAL ( clEnqueueNDRangeKernel(clCommandQueue, fft_kernel, 1, 0,
                            grid, block, 0, 0, 0) ); 	
  pb_SwitchToTimer(&timers, pb_TimerID_COPY);

  // copy device memory to host
  OCL_ERRCK_RETVAL( clEnqueueReadBuffer(clCommandQueue, d_source, CL_TRUE, 
                        0, // Offset in bytes
                        n_bytes, // Size of data to read
                        result, // Host Source
                        0, NULL, NULL) );
                        
  if (params->outFile) {
    /* Write result to file */
    pb_SwitchToTimer(&timers, pb_TimerID_IO);
    outputData(params->outFile, (float*)result, N*B*2);
    pb_SwitchToTimer(&timers, pb_TimerID_COMPUTE);
  }

  OCL_ERRCK_RETVAL ( clReleaseMemObject(d_source) );
  OCL_ERRCK_RETVAL ( clReleaseMemObject(d_work) );
  OCL_ERRCK_RETVAL ( clReleaseMemObject(d_shared_source) );
  pb_SwitchToTimer(&timers, pb_TimerID_COMPUTE);

  free(shared_source);  
  free(source);
  free(result);
  pb_SwitchToTimer(&timers, pb_TimerID_NONE);
  pb_PrintTimerSet(&timers);
  
  pb_DestroyTimerSet(&timers);
  
  return 0;
}
Ejemplo n.º 6
0
void GitCommand::run()
{
    if (Git::Constants::debug)
        qDebug() << "GitCommand::run" << m_workingDirectory << m_jobs.size();
    QProcess process;
    if (!m_workingDirectory.isEmpty())
        process.setWorkingDirectory(m_workingDirectory);

    process.setEnvironment(m_environment);

    QByteArray stdOut;
    QByteArray stdErr;
    QString error;

    const int count = m_jobs.size();
    int exitCode = -1;
    bool ok = true;
    for (int j = 0; j < count; j++) {
        if (Git::Constants::debug)
            qDebug() << "GitCommand::run" << j << '/' << count << m_jobs.at(j).arguments;

        process.start(m_binaryPath, m_basicArguments + m_jobs.at(j).arguments);
        if(!process.waitForStarted()) {
            ok = false;
            error += QString::fromLatin1("Error: \"%1\" could not be started: %2").arg(m_binaryPath, process.errorString());
            break;
        }

        process.closeWriteChannel();
        const int timeOutSeconds = m_jobs.at(j).timeout;
        if (!Utils::SynchronousProcess::readDataFromProcess(process, timeOutSeconds * 1000,
                                                            &stdOut, &stdErr)) {
            Utils::SynchronousProcess::stopProcess(process);
            ok = false;
            error += msgTimeout(timeOutSeconds);
            break;
        }

        error += QString::fromLocal8Bit(stdErr);
        exitCode = process.exitCode();
        switch (m_reportTerminationMode) {
        case NoReport:
            break;
        case ReportStdout:
            stdOut += msgTermination(exitCode, m_binaryPath, m_jobs.at(j).arguments).toUtf8();
            break;
        case ReportStderr:
            error += msgTermination(exitCode, m_binaryPath, m_jobs.at(j).arguments);
            break;
        }
    }

    // Special hack: Always produce output for diff
    if (ok && stdOut.isEmpty() && m_jobs.front().arguments.at(0) == QLatin1String("diff")) {
        stdOut += "The file does not differ from HEAD";
    } else {
        // @TODO: Remove, see below
        if (ok && m_jobs.front().arguments.at(0) == QLatin1String("status"))
            removeColorCodes(&stdOut);
    }

    if (ok && !stdOut.isEmpty())
        emit outputData(stdOut);

    if (!error.isEmpty())
        emit errorText(error);

    emit finished(ok, exitCode, m_cookie);
    if (ok)
        emit success();
    // As it is used asynchronously, we need to delete ourselves
    this->deleteLater();
}