Changeset 484 for trunk/src/corelib/io


Ignore:
Timestamp:
Jan 28, 2010, 10:53:18 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

corelib: Fixed: QProcess::startDetached() would either crash or fail to start a process.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/corelib/io/qprocess_os2.cpp

    r440 r484  
    749749                           const QStringList *environment, bool detached = false)
    750750{
    751     int mode = detached ? P_DETACH : P_NOWAIT;
     751    int mode = detached ? P_ : P_NOWAIT;
    752752
    753753    // Create argument list with right number of elements (one extra is for
     
    916916        const char **argvReal = argv;
    917917
    918         if (mode == P_DETACH) {
    919             // @todo P_DETACH isn't supported by kLIBC atm, prepend the program
    920             // to start with "cmd.exe /c detach" as a temporary solution
    921             mode = P_NOWAIT;
    922             programReal = getenv("COMSPEC"); // returns static!
    923             if (programReal == 0)
    924                 programReal = "cmd.exe";
    925             argvReal = argvBase;
    926             argvReal[0] = programReal;
    927             argvReal[1] = "/c";
    928             argvReal[2] = "detach";
    929             argv[0] = fullProgramName.data();
     918        if (mode == P_SESSION) {
     919            // @todo P_SESSION isn't supported by kLIBC atm, use DosStartSession
     920            // below
    930921        } else {
    931922            // get the application type of our program (note that we cannot use
     
    968959        // spawnve we have to perform a pointless cast; the devinition for the
    969960        // 3rd and 4th arg should be: char const * const *)
    970         pid = spawnve(mode, programReal, const_cast<char * const *>(argvReal), envv);
     961        if (mode == P_SESSION) {
     962            // @todo P_SESSION isn't supported by kLIBC atm, use DosStartSession
     963            bool needCmd = false;
     964            int dot = fullProgramName.lastIndexOf('.');
     965            Q_ASSERT(dot > 0);
     966            if (dot > 0)
     967                needCmd = qstricmp(fullProgramName.data() + dot, ".cmd") == 0 ||
     968                          qstricmp(fullProgramName.data() + dot, ".bat") == 0;
     969
     970            QByteArray args;
     971            foreach(const QString &arg, arguments)
     972                if (!arg.isEmpty())
     973                    args += '"' + QFile::encodeName(arg) + '"';
     974            if (needCmd) {
     975                args.prepend("\" ");
     976                args.prepend(programReal);
     977                args.prepend("/C \"");
     978                programReal = getenv("COMSPEC"); // returns static!
     979                if (programReal == 0)
     980                    programReal = "cmd.exe";
     981             }
     982
     983            QByteArray env;
     984            if (envv != environ)
     985                for (char **e = envv; *e; ++e)
     986                    env += *e + '\0';
     987
     988            STARTDATA data;
     989            data.Length = sizeof(data);
     990            data.Related = SSF_RELATED_INDEPENDENT;
     991            data.FgBg = SSF_FGBG_FORE;
     992            data.TraceOpt = SSF_TRACEOPT_NONE;
     993            data.PgmTitle = 0;
     994            data.PgmName = (PSZ)programReal;
     995            data.PgmInputs = args.data();
     996            data.TermQ = 0;
     997            data.Environment = env.isEmpty() ? 0 : env.data();
     998            data.InheritOpt = SSF_INHERTOPT_PARENT;
     999            data.SessionType = SSF_TYPE_DEFAULT;
     1000            data.IconFile = 0;
     1001            data.PgmHandle = 0;
     1002            data.PgmControl = SSF_CONTROL_VISIBLE;
     1003            data.InitXPos = data.InitYPos = data.InitXSize = data.InitYSize = 0;
     1004            data.Reserved = 0;
     1005            data.ObjectBuffer = 0;
     1006            data.ObjectBuffLen = 0;
     1007
     1008            ULONG ulSid, ulPid;
     1009            if (DosStartSession(&data, &ulSid, &ulPid) == NO_ERROR)
     1010                pid = ulPid;
     1011        } else {
     1012            pid = spawnve(mode, programReal, const_cast<char * const *>(argvReal), envv);
     1013        }
    9711014
    9721015#if defined(QPROCESS_DEBUG)
     
    16571700        return false;
    16581701
    1659     *pid = startedPid;
     1702    if (pid)
     1703        *pid = startedPid;
    16601704    return true;
    16611705}
Note: See TracChangeset for help on using the changeset viewer.