Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Замещение родительского процесса дочерним 
V
    Опции темы
alexx83
Дата 20.12.2012, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Добрый день!
Необходимо решить следующую задачу:
 Имеются 2 консольных приложения, одно и которых при запуске меняет часть переменных среды и запускает второе приложение с заданными параметрами. Второе приложение должно взаимодействовать с вводом-выводом в консоль. На данный момент это реализовано через CreateProcess, при этом второму процессу передаются хэндлы ввода-вывода и в принципе все нормально отрабатывает. Но есть одно НО. При несанкционированном завершении родительского процесса, например через диспетчер задач, дочерний процесс остается висеть в памяти. 
  Необходимо в идеальном случае замещать родительский процесс дочерним с сохранением взаимодействия с консолью в дочернем процессе. На данном этапе набросан черновик с использованием _execvpe, при вызове которого родительский процесс замещается дочерним. Возникла проблема с вводом-выводом в консоль из дочернего процесса. При запуске дочернего процесса, он выводит некоторую информацию в консоль, но при попытке пользовательского ввода с клавиатуры возникает ошибка:
Код

Exception condition detected on fd 0
error detected on stdin

После чего дочерний процесс висит в памяти но консоль с ним уже не связана.
Кто-нибудь сталкивался с подобным или знает пути решения?
Заранее спасибо!
PM MAIL   Вверх
feodorv
Дата 20.12.2012, 22:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Непонятно. 
Цитата(alexx83 @  20.12.2012,  22:45 Найти цитируемый пост)
На данный момент это реализовано через CreateProcess

Не могли бы Вы дать параметры этого вызова.


Цитата(alexx83 @  20.12.2012,  22:45 Найти цитируемый пост)
запускает второе приложение с заданными параметрами
 
Цитата(alexx83 @  20.12.2012,  22:45 Найти цитируемый пост)
Необходимо в идеальном случае замещать родительский процесс дочерним
 
Цитата(alexx83 @  20.12.2012,  22:45 Найти цитируемый пост)
При несанкционированном завершении родительского процесса, например через диспетчер задач
 Почему тогда родительский процесс просто не завершается? Зачем ему дожидаться завершения дочернего?


Цитата(alexx83 @  20.12.2012,  22:45 Найти цитируемый пост)
с использованием _execvpe

_execvpe вызывает тот же CreateProcess, а потом exit(0)...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
alexx83
Дата 21.12.2012, 08:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Через CreateProcess вызываю так:
Код

memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
memset(&pi, 0, sizeof(pi));

CreateProcess(
    0    // exe name
    ,cmdbuf    // command line
    ,0            // process security attributes
    ,0            // primary thread security attributes
    ,FALSE        // handles are NOT inherited
    ,0            // creation flags
    ,0            // use parent's environment
    ,0            // use parent's current directory
    ,&si        // STARTUPINFO pointer
    ,&pi        // receives PROCESS_INFORMATION
)

WaitForSingleObject(pi.hProcess, INFINITE);
    
GetExitCodeProcess(pi.hProcess, &exitCode)
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );


PM MAIL   Вверх
alexx83
Дата 21.12.2012, 11:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Можете показать реализацию _execvpe?
PM MAIL   Вверх
feodorv
Дата 21.12.2012, 19:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(alexx83 @  21.12.2012,  09:02 Найти цитируемый пост)
Через CreateProcess вызываю так:

Вроде, всё на месте))) Поясните тогда, пожалуйста:
Цитата(alexx83 @  20.12.2012,  22:45 Найти цитируемый пост)
При несанкционированном завершении родительского процесса, например через диспетчер задач, дочерний процесс остается висеть в памяти. 

Дочерний процесс в конце концов не завершается самостоятельно, или же просто Вам хочется, чтобы он умирал синхронно со смертью родительского?


Цитата(alexx83 @  20.12.2012,  22:45 Найти цитируемый пост)
Необходимо в идеальном случае замещать родительский процесс дочерним с сохранением взаимодействия с консолью в дочернем процессе.

Почему тогда
Цитата(alexx83 @  21.12.2012,  09:02 Найти цитируемый пост)
WaitForSingleObject(pi.hProcess, INFINITE);

Почему не завершать родительский процесс сразу (ну, или после WaitForInputIdle)? Дочерний процесс теряет способность взаимодействия с консолью?


Цитата(alexx83 @  21.12.2012,  12:25 Найти цитируемый пост)
Можете показать реализацию _execvpe? 

Могу, но кода много и он относится к MSVS C++ 6.0.

Добавлено через 1 минуту и 35 секунд
Файл Execvpe.c
Код

/***
*execvpe.c - execute a file with given environ; search along PATH
*
*       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines _execvpe() - execute a file with given environ
*
*******************************************************************************/

#include <cruntime.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include <mbstring.h>
#include <tchar.h>
#include <dbgint.h>

#define SLASHCHAR _T('\\')
#define XSLASHCHAR _T('/')

#define SLASH _T("\\")
#define DELIMITER _T(";")

#ifdef _MBCS
/* note, the macro below assumes p is to pointer to a single-byte character
 * or the 1st byte of a double-byte character, in a string.
 */
#define ISPSLASH(p)     ( ((p) == _mbschr((p), SLASHCHAR)) || ((p) == \
_mbschr((p), XSLASHCHAR)) )
#else  /* _MBCS */
#define ISSLASH(c)      ( ((c) == SLASHCHAR) || ((c) == XSLASHCHAR) )
#endif  /* _MBCS */


/***
*int _execvpe(filename, argvector, envvector) - execute a file
*
*Purpose:
*       Executes a file with given arguments and environment.
*       try to execute the file. start with the name itself (directory '.'),
*       and if that doesn't work start prepending pathnames from the
*       environment until one works or we run out. if the file is a pathname,
*       don't go to the environment to get alternate paths. If a needed text
*       file is busy, wait a little while and try again before despairing
*       completely
*
*Entry:
*       _TSCHAR *filename        - file to execute
*       _TSCHAR **argvector - vector of arguments
*       _TSCHAR **envvector - vector of environment variables
*
*Exit:
*       destroys the calling process (hopefully)
*       if fails, returns -1
*
*Exceptions:
*
*******************************************************************************/

int __cdecl _texecvpe (
        REG3 const _TSCHAR *filename,
        const _TSCHAR * const *argvector,
        const _TSCHAR * const *envptr
        )
{
        REG1 _TSCHAR *env;
        _TSCHAR *bbuf = NULL;
        REG2 _TSCHAR *buf;
        _TSCHAR *pfin;

        _ASSERTE(filename != NULL);
        _ASSERTE(*filename != _T('\0'));
        _ASSERTE(argvector != NULL);
        _ASSERTE(*argvector != NULL);
        _ASSERTE(**argvector != _T('\0'));

        _texecve(filename,argvector,envptr);

        if ( (errno != ENOENT)
        || (_tcschr(filename, SLASHCHAR) != NULL)
        || (_tcschr(filename, XSLASHCHAR) != NULL)
        || *filename && *(filename+1) == _T(':')
        || !(env=_tgetenv(_T("PATH"))) )
                goto reterror;

        /* allocate a buffer to hold alternate pathnames for the executable
         */
        if ( (buf = bbuf = _malloc_crt(_MAX_PATH * sizeof(_TSCHAR))) == NULL )
            goto reterror;

        do {
                /* copy a component into bbuf[], taking care not to overflow it
                 */
                /* UNDONE: make sure ';' isn't 2nd byte of DBCS char */
                while ( (*env) && (*env != _T(';')) && (buf < bbuf+(_MAX_PATH-2)*sizeof(_TSCHAR)) )
                        *buf++ = *env++;

                *buf = _T('\0');
                pfin = --buf;
                buf = bbuf;

#ifdef _MBCS
                if (*pfin == SLASHCHAR) {
                        if (pfin != _mbsrchr(buf,SLASHCHAR))
                                /* *pfin is the second byte of a double-byte
                                 * character
                                 */
                                strcat( buf, SLASH );
                }
                else if (*pfin != XSLASHCHAR)
                        strcat(buf, SLASH);
#else  /* _MBCS */
                if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR)
                        _tcscat(buf, SLASH);
#endif  /* _MBCS */

                /* check that the final path will be of legal size. if so,
                 * build it. otherwise, return to the caller (return value
                 * and errno rename set from initial call to _execve()).
                 */
                if ( (_tcslen(buf) + _tcslen(filename)) < _MAX_PATH )
                        _tcscat(buf, filename);
                else
                        break;

                _texecve(buf, argvector, envptr);

                if ( (errno != ENOENT)
#ifdef _MBCS
                && (!ISPSLASH(buf) || !ISPSLASH(buf+1)) )
#else  /* _MBCS */
                && (!ISSLASH(*buf) || !ISSLASH(*(buf+1))) )
#endif  /* _MBCS */
                        break;
        } while ( *env && env++ );

reterror:
        if (bbuf != NULL)
                _free_crt(bbuf);

        return(-1);
}


Добавлено через 2 минуты и 29 секунд
Файл Execve.c
Код

/***
*execve.c - execute a file with a given environment
*
*       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines _execve() - execute a file
*
*******************************************************************************/

#define EXECVE

#include "spawnve.c"


Добавлено через 3 минуты и 43 секунды
Файл Spawnve.c
Код

/***
*spawnve.c - Low level routine eventually called by all _spawnXX routines
*       also contains all code for _execve, called by _execXX routines
*
*       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
*
*       This is the low level routine which is eventually invoked by all the
*       _spawnXX routines.
*
*       This is also the low-level routine which is eventually invoked by
*       all of the _execXX routines.
*
*******************************************************************************/

#include <cruntime.h>
#include <io.h>
#include <process.h>
#include <errno.h>
#include <msdos.h>
#include <string.h>
#include <stdlib.h>
#include <internal.h>
#include <mbstring.h>
#include <tchar.h>
#include <dbgint.h>

#define SLASHCHAR   _T('\\')
#define XSLASHCHAR  _T('/')

#ifndef EXECVE
#ifdef WPRFLAG
static int __cdecl wcomexecmd(int mode, const wchar_t * name,
        const wchar_t * const * argv, const wchar_t * const * envp);
#else  /* WPRFLAG */
static int __cdecl comexecmd(int mode, const char * name,
        const char * const * argv, const char * const * envp);
#endif  /* WPRFLAG */
#else  /* EXECVE */
#ifdef WPRFLAG
static int __cdecl wcomexecmd(const wchar_t * name,
        const wchar_t * const * argv, const wchar_t * const * envp);
#else  /* WPRFLAG */
static int __cdecl comexecmd(const char * name,
        const char * const * argv, const char * const * envp);
#endif  /* WPRFLAG */
#endif  /* EXECVE */

/***
*static int comexecmd(mode, name, argv, envp) - do the exec
*       or spawn after name fixup
*
*Purpose:
*       Spawns a child process with given parameters and environment.  Either
*       overlays current process or loads in free memory while parent process
*       waits.  If the named file is a .cmd file, modifies the calling sequence
*       and prepends the /c and filename arguments into the command string
*
*       Exec doesn't take a mode; instead, the parent process goes away as
*       the child process is brought in.
*
*Entry:
*       int mode - mode to spawn (WAIT, NOWAIT, or OVERLAY)
*                   only WAIT and OVERLAY currently supported
*
*           ****  mode is only used in the spawnve() version  ****
*
*       _TSCHAR *name - pathname of file to spawn.  Includes the extension
*       _TSCHAR **argv - vector of parameter strings
*       _TSCHAR **envp - vector of environment variables
*
*Exit:
*       returns exit code of child process
*       if fails, returns -1
*
*Exceptions:
*       Returns a value of (-1) to indicate an error in exec'ing the child
*       process.  errno may be set to:
*
*       E2BIG   = failed in argument/environment processing (_cenvarg)
*                 argument list or environment too big;
*       EACCESS = locking or sharing violation on file;
*       EMFILE  = too many files open;
*       ENOENT  = failed to find program name - no such file or directory;
*       ENOEXEC = failed in exec - bad executable format;
*       ENOMEM  = failed in memory allocation (during malloc, or in
*                 setting up memory for executing child process).
*
*******************************************************************************/

#ifdef WPRFLAG
static int __cdecl wcomexecmd (
#else  /* WPRFLAG */
static int __cdecl comexecmd (
#endif  /* WPRFLAG */

#ifndef EXECVE
        REG3 int mode,
#endif  /* EXECVE */

        REG2 const _TSCHAR *name,
        const _TSCHAR * const *argv,
        const _TSCHAR * const *envp
        )
{
        _TSCHAR *argblk;
        _TSCHAR *envblk;
        REG4 int rc;

#ifdef WPRFLAG
        if (_wcenvarg(argv, envp, &argblk, &envblk, name) == -1)
#else  /* WPRFLAG */
        if (_cenvarg(argv, envp, &argblk, &envblk, name) == -1)
#endif  /* WPRFLAG */
                return -1;

#ifndef EXECVE
#ifdef WPRFLAG
        rc = _wdospawn(mode, name, argblk, envblk);
#else  /* WPRFLAG */
        rc = _dospawn(mode, name, argblk, envblk);
#endif  /* WPRFLAG */
#else  /* EXECVE */
#ifdef WPRFLAG
        rc = _wdospawn(_P_OVERLAY, name, argblk, envblk);
#else  /* WPRFLAG */
        rc = _dospawn(_P_OVERLAY, name, argblk, envblk);
#endif  /* WPRFLAG */
#endif  /* EXECVE */
        /* free memory */

        _free_crt(argblk);
        _free_crt(envblk);

        return rc;
}

/***
*int _spawnve(mode, name, argv, envp) - low level _spawnXX library function
*int _execve(name, argv, envp) - low level _execXX library function
*
*Purpose:
*       spawns or execs a child process; takes a single pointer to an argument
*       list as well as a pointer to the environment; unlike _spawnvpe,
*       _spawnve does not search the PATH= list in processing the name
*       parameter; mode specifies the parent's execution mode.
*
*Entry:
*       int mode    - parent process's execution mode:
*                     must be one of _P_OVERLAY, _P_WAIT, _P_NOWAIT;
*                     not used for _execve
*       _TSCHAR *name  - path name of program to spawn;
*       _TSCHAR **argv - pointer to array of pointers to child's arguments;
*       _TSCHAR **envp - pointer to array of pointers to child's environment
*                     settings.
*
*Exit:
*       Returns : (int) a status value whose meaning is as follows:
*               0        = normal termination of child process;
*               positive = exit code of child upon error termination
*                          (abort or exit(nonzero));
*               -1       = child process was not spawned;
*                          errno indicates what kind of error:
*                          (E2BIG, EINVAL, ENOENT, ENOEXEC, ENOMEM).
*
*Exceptions:
*       Returns a value of (-1) to indicate an error in spawning the child
*       process.  errno may be set to:
*
*       E2BIG   = failed in argument/environment processing (_cenvarg) -
*                 argument list or environment too big;
*       EINVAL  = invalid mode argument;
*       ENOENT  = failed to find program name - no such file or directory;
*       ENOEXEC = failed in spawn - bad executable format;
*       ENOMEM  = failed in memory allocation (during malloc, or in
*                 setting up memory for spawning child process).
*
*******************************************************************************/

/* Extension array - ordered in search order from right to left.

   ext_strings  = array of extensions
*/

static _TSCHAR *ext_strings[] = { _T(".cmd"), _T(".bat"), _T(".exe"), _T(".com") };
enum {CMD, BAT, EXE, COM, EXTFIRST=CMD, EXTLAST=COM};

int __cdecl

#ifndef EXECVE

_tspawnve (
        REG3 int mode,

#else  /* EXECVE */

_texecve (

#endif  /* EXECVE */

        const _TSCHAR *name,
        const _TSCHAR * const *argv,
        const _TSCHAR * const *envp
        )
{
        _TSCHAR *ext;   /* where the extension goes if we have to add one */
        REG1 _TSCHAR *p;
        _TSCHAR *q;
        REG2 _TSCHAR *pathname = (_TSCHAR *)name;
        REG4 int rc;
        REG5 int i;

        p = _tcsrchr(pathname, SLASHCHAR);
        q = _tcsrchr(pathname, XSLASHCHAR);

        /* ensure that pathname is an absolute or relative pathname. also,
         * position p to point at the filename portion of pathname (i.e., just
         * after the last occurence of a colon, slash or backslash character */

        if (!q) {
                if (!p)
                        if (!(p = _tcschr(pathname, _T(':')))) {

                                /* pathname is a filename only, force it to be
                                 * a relative pathname. note that an extra byte
                                 * is malloc-ed just in case pathname is NULL,
                                 * to keep the heap from being trashed by
                                 * strcpy */
                                if (!(pathname = _malloc_crt((_tcslen(pathname) + 3) * sizeof(_TSCHAR))))
                                        return(-1);

                                _tcscpy(pathname, _T(".\\"));
                                _tcscat(pathname, name);

                                /* set p to point to the start of the filename
                                 * (i.e., past the ".\\" prefix) */
                                p = pathname + 2;
                        }
                        /* else pathname has drive specifier prefix and p is
                         * is pointing to the ':' */
        }
        else if (!p || q > p)   /* p == NULL or q > p */
                p = q;


        rc = -1;        /* init to error value */

        if (ext = _tcsrchr(p, _T('.')))  {

                /* extension given; only do filename */

                if (_taccess(pathname, 0) != -1) {

#ifndef EXECVE

#ifdef WPRFLAG
                        rc = wcomexecmd(mode, pathname, argv, envp);
#else  /* WPRFLAG */
                        rc = comexecmd(mode, pathname, argv, envp);
#endif  /* WPRFLAG */

#else  /* EXECVE */

#ifdef WPRFLAG
                        rc = wcomexecmd(pathname, argv, envp);
#else  /* WPRFLAG */
                        rc = comexecmd(pathname, argv, envp);
#endif  /* WPRFLAG */

#endif  /* EXECVE */
                }

        }
        else    {

                /* no extension; try .cmd/.bat, then .com and .exe */

                if (!(p = _malloc_crt((_tcslen(pathname) + 5) * sizeof(_TSCHAR))))
                        return(-1);

                _tcscpy(p, pathname);
                ext = p + _tcslen(pathname);

                for (i = EXTLAST; i >= EXTFIRST; --i) {
                        _tcscpy(ext, ext_strings[i]);

                        if (_taccess(p, 0) != -1) {

#ifndef EXECVE
#ifdef WPRFLAG
                                rc = wcomexecmd(mode, p, argv, envp);
#else  /* WPRFLAG */
                                rc = comexecmd(mode, p, argv, envp);
#endif  /* WPRFLAG */
#else  /* EXECVE */
#ifdef WPRFLAG
                                rc = wcomexecmd(p, argv, envp);
#else  /* WPRFLAG */
                                rc = comexecmd(p, argv, envp);
#endif  /* WPRFLAG */
#endif  /* EXECVE */
                                break;
                        }
                }
                _free_crt(p);
        }

        if (pathname != name)
                _free_crt(pathname);

        return rc;
}


Добавлено через 6 минут и 17 секунд
Остальное через 15 минут)))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
alexx83
Дата 21.12.2012, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



На работе вроде отправлял сообщение сюда что реализацию _execvpe нашел которую вы выложили. Все равно спасибо! Не нашел только реализацию функции comexecmd() - msdn ничего не нашел и в студии тоже не нашел. 

Цитата

Дочерний процесс в конце концов не завершается самостоятельно, или же просто Вам хочется, чтобы он умирал синхронно со смертью родительского?

Да нужно чтобы процессы умирали синхронно.

Цитата

Почему не завершать родительский процесс сразу (ну, или после WaitForInputIdle)? Дочерний процесс теряет способность взаимодействия с консолью?

А можно по подробнее? После CreateProcess просто делать exit?
PM MAIL   Вверх
feodorv
Дата 21.12.2012, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Файл Dospawn.c
Код

/***
*dospawn.c - spawn a child process
*
*       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines _dospawn - spawn a child process
*
*******************************************************************************/

#include <cruntime.h>
#include <oscalls.h>
#include <internal.h>
#include <msdos.h>
#include <process.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <tchar.h>
#include <dbgint.h>

#ifndef WPRFLAG
int _p_overlay = 2;
#endif  /* WPRFLAG */

/***
*int _dospawn(mode, name, cmdblk, envblk) - spawn a child process
*
*Purpose:
*       Spawns a child process
*
*Entry:
*       int mode     - _P_WAIT, _P_NOWAIT, _P_NOWAITO, _P_OVERLAY, or _P_DETACH
*       _TSCHAR *name   - name of program to execute
*       _TSCHAR *cmdblk - parameter block
*       _TSCHAR *envblk - environment block
*
*Exit:
*       _P_OVERLAY: -1 = error, otherwise doesn't return
*       _P_WAIT:    termination code << 8 + result code
*       _P_DETACH: -1 = error, 0 = success
*       others:    PID of process
*
*Exceptions:
*
*******************************************************************************/

#ifdef WPRFLAG
int __cdecl _wdospawn (
#else  /* WPRFLAG */
int __cdecl _dospawn (
#endif  /* WPRFLAG */
        int mode,
        const _TSCHAR *name,
        _TSCHAR *cmdblk,
        _TSCHAR *envblk
        )
{
        char syncexec, asyncresult, background;
        LPTSTR CommandLine;
        STARTUPINFO StartupInfo;
        PROCESS_INFORMATION ProcessInformation;
        BOOL CreateProcessStatus;
        ULONG dosretval;                /* OS return value */
        DWORD retval;
        DWORD fdwCreate = 0;            /* flags for CreateProcess */
        int i;
        ioinfo *pio;
        char *posfile;
        UNALIGNED long *posfhnd;
        int nh;                         /* number of file handles to be
                                           passed to the child */

        /* translate input mode value to individual flags */
        syncexec = asyncresult = background = 0;
        switch (mode) {
        case _P_WAIT:    syncexec=1;    break;  /* synchronous execution */
        case 2: /* _P_OVERLAY */
        case _P_NOWAITO: break;                 /* asynchronous execution */
        case _P_NOWAIT:  asyncresult=1; break;  /* asynch + remember result */
        case _P_DETACH:  background=1;  break;  /* detached in null scrn grp */
        default:
            /* invalid mode */
            errno = EINVAL;
            _doserrno = 0;              /* not a Dos error */
            return -1;
        }

        /*
         * Loop over null separate arguments, and replace null separators
         * with spaces to turn it back into a single null terminated
         * command line.
         */
        CommandLine = cmdblk;
        while (*cmdblk) {
            while (*cmdblk) {
                cmdblk++;
            }

            /*
             * If not last argument, turn null separator into a space.
             */
            if (cmdblk[1] != _T('\0')) {
                *cmdblk++ = _T(' ');
            }
        }

        memset(&StartupInfo,0,sizeof(StartupInfo));
        StartupInfo.cb = sizeof(StartupInfo);

        for ( nh = _nhandle ;
              nh && !_osfile(nh - 1) ;
              nh-- ) ;

        StartupInfo.cbReserved2 = (WORD)(sizeof( int ) + (nh *
                                  (sizeof( char ) + sizeof( long ))));

        StartupInfo.lpReserved2 = _calloc_crt( StartupInfo.cbReserved2, 1 );

        *((UNALIGNED int *)(StartupInfo.lpReserved2)) = nh;

        posfile = (char *)(StartupInfo.lpReserved2 + sizeof( int ));

        posfhnd = (UNALIGNED long *)(StartupInfo.lpReserved2 + sizeof( int ) +
                  (nh * sizeof( char )));

        for ( i = 0,
              posfile = (char *)(StartupInfo.lpReserved2 + sizeof( int )),
              posfhnd = (UNALIGNED long *)(StartupInfo.lpReserved2 +
                        sizeof( int ) + (nh * sizeof( char ))) ;
              i < nh ;
              i++, posfile++, posfhnd++ )
        {
            pio = _pioinfo(i);
            if ( (pio->osfile & FNOINHERIT) == 0 ) {
                *posfile = pio->osfile;
                *posfhnd = pio->osfhnd;
            }
            else {
                *posfile = 0;
                *posfhnd = (long)INVALID_HANDLE_VALUE;
            }
        }

        /*
         * if the child process is detached, it cannot access the console, so
         * we must nuke the information passed for the first three handles.
         */
        if ( background ) {

            for ( i = 0,
                  posfile = (char *)(StartupInfo.lpReserved2 + sizeof( int )),
                  posfhnd = (UNALIGNED long *)(StartupInfo.lpReserved2 + sizeof( int )
                            + (nh * sizeof( char ))) ;
                  i < __min( nh, 3 ) ;
                  i++, posfile++, posfhnd++ )
            {
                *posfile = 0;
                *posfhnd = (long)INVALID_HANDLE_VALUE;
            }

            fdwCreate |= DETACHED_PROCESS;
        }

        /**
         * Set errno to 0 to distinguish a child process
         * which returns -1L from an error in the spawning
         * (which will set errno to something non-zero
        **/

        _doserrno = errno = 0 ;

#ifdef WPRFLAG
        /* indicate to CreateProcess that environment block is wide */
        fdwCreate |= CREATE_UNICODE_ENVIRONMENT;
#endif  /* WPRFLAG */

        CreateProcessStatus = CreateProcess( (LPTSTR)name,
                                             CommandLine,
                                             NULL,
                                             NULL,
                                             TRUE,
                                             fdwCreate,
                                             envblk,
                                             NULL,
                                             &StartupInfo,
                                             &ProcessInformation
                                           );

        dosretval = GetLastError();
        _free_crt( StartupInfo.lpReserved2 );

        if (!CreateProcessStatus) {
            _dosmaperr(dosretval);
            return -1;
        }

        if (mode == 2 /* _P_OVERLAY */) {
            /* destroy ourselves */
            _exit(0);
        }
        else if (mode == _P_WAIT) {
            WaitForSingleObject(ProcessInformation.hProcess, (DWORD)(-1L));

            /* return termination code and exit code -- note we return
               the full exit code */
            GetExitCodeProcess(ProcessInformation.hProcess, &retval);

            CloseHandle(ProcessInformation.hProcess);
        }
        else if (mode == _P_DETACH) {
            /* like totally detached asynchronous spawn, dude,
               close process handle, return 0 for success */
            CloseHandle(ProcessInformation.hProcess);
            retval = (DWORD)0;
        }
        else {
            /* asynchronous spawn -- return PID */
            retval = (DWORD)ProcessInformation.hProcess;
        }

        CloseHandle(ProcessInformation.hThread);
        return retval;
}


Добавлено через 8 минут и 13 секунд
Цитата(alexx83 @  21.12.2012,  20:45 Найти цитируемый пост)
Да нужно чтобы процессы умирали синхронно.

Это делается через job'ы.


Цитата(alexx83 @  21.12.2012,  20:45 Найти цитируемый пост)
А можно по подробнее? После CreateProcess просто делать exit? 

Из main (etc) можно просто return))) Или ExitProcess. exit - это как-то для stdlib.
Но я бы предварительно сделал WaitForInputIdle на всякий случай...


Цитата(alexx83 @  21.12.2012,  20:45 Найти цитируемый пост)
Не нашел только реализацию функции comexecmd()

См. вышеприведённый файл Spawnve.c smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
alexx83
Дата 21.12.2012, 20:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Если делаю так:
Код

CreateProcess(
    0    // exe name
    ,cmdbuf    // command line
    ,0            // process security attributes
    ,0            // primary thread security attributes
    ,FALSE        // handles are NOT inherited
    ,0            // creation flags
    ,0            // use parent's environment
    ,0            // use parent's current directory
    ,&si        // STARTUPINFO pointer
    ,&pi        // receives PROCESS_INFORMATION
);
    
WaitForInputIdle(pi.hProcess, INFINITE);
    
free(envbuf);
free(resbuf);
free(cmdbuf);
    
ExitProcess(0);

То получаю такой же результат как при использовании _execvpe, т.е. могу ввести только одну команду в консоли дочернему процессу и он отрубается от консоли
PM MAIL   Вверх
alexx83
Дата 21.12.2012, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Сделал через jobs:
Код

HANDLE ghJob = CreateJobObject( NULL, "Gdb-Wrapper\0"/*NULL*/);
if( ghJob == NULL)
{
    printf("Could not create job object\n");
}
else
{
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
    // Configure all child processes associated with the job to terminate when the
    jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
    if( 0 == SetInformationJobObject( ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
    {
        printf("Could not SetInformationJobObject\n");
    }
}

memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
    
memset(&pi, 0, sizeof(pi));

CreateProcess(
    0    // exe name
    ,cmdbuf    // command line
    ,0            // process security attributes
    ,0            // primary thread security attributes
    ,FALSE        // handles are NOT inherited
    ,0            // creation flags
    ,0            // use parent's environment
    ,0            // use parent's current directory
    ,&si        // STARTUPINFO pointer
    ,&pi        // receives PROCESS_INFORMATION
);
    
if( 0 == AssignProcessToJobObject( ghJob, pi.hProcess))
{
    printf("Could not AssignProcessToObject\n");
}
WaitForSingleObject(pi.hProcess, INFINITE);

GetExitCodeProcess(pi.hProcess, &exitCode);
    
//CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
    
free(envbuf);
free(resbuf);
free(cmdbuf);
    
return exitCode;

Единственное если снимаю родительский процесс через менеджер процессов, то опять получаю:
Код

$ Exception condition detected on fd 0
error detected on stdin

Можно от этого избавиться?
PM MAIL   Вверх
feodorv
Дата 21.12.2012, 23:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(alexx83 @  21.12.2012,  21:27 Найти цитируемый пост)
То получаю такой же результат как при использовании _execvpe, т.е. могу ввести только одну команду в консоли дочернему процессу и он отрубается от консоли 

Даже не знаю, что сказать. Я бы ещё поэкспериментировал с флагом наследования, с GetConsoleProcessList() и т.д., но на всё это нужно время...

 
Цитата(alexx83 @  21.12.2012,  22:21 Найти цитируемый пост)
Единственное если снимаю родительский процесс через менеджер процессов, то опять получаю:

Опять-таки, не знаю, чем помочь...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
boostcoder
Дата 22.12.2012, 00:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: нет
Всего: 110



feodorv, здравствуй.
уже и мне сабж любопытен.

давай начнем сначала, а то я запутался...
скажи, каким образом я могу запустить дочерний процесс так, чтоб он унаследовал дескрипторы стандартного ввода/вывода, и чтоб по завершению родительского процесса завершался дочерний?
в линукс это решается банальным использованием fork() в родительском, и exec*() в дочернем.

спасибо.

PM WWW   Вверх
boostcoder
Дата 22.12.2012, 00:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: нет
Всего: 110



но в данном случае fork() лишний, да.

PM WWW   Вверх
feodorv
Дата 22.12.2012, 04:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



boostcoder, здравствуй  smile 

К сожалению, Windows - вещь в себе, и часто приходится искать неочевидные решения, использовать неочевидные опции (среди многочисленных подобных), чтобы добиться желаемого результата.


Цитата(boostcoder @  22.12.2012,  01:04 Найти цитируемый пост)
скажи, каким образом я могу запустить дочерний процесс так, чтоб он унаследовал дескрипторы стандартного ввода/вывода

Это первая часть вопроса, не менее важная, чем вторая. Вот здесь сказано, что если при вызове CreateProcess (для консольного экзешника) не пользоваться флагами  CREATE_NEW_CONSOLE и DETACHED_PROCESS, то дочерний процесс остаётся прикреплённым к консоли родительского процесса. Правда, я лично обычно всё же выставлял bInheritHandles в TRUE, а в STARTUPINFO устанавливал стандартные хендлеры не смотря на то, что это, вроде, и не требуется:
Цитата
the parent's standard handles are inherited by any child process
 (заимствовано отсюда), но никогда не прибивал родительский процесс раньше времени, чтобы посмотреть, что там случилось с дочерним. Там же нашёл интересную фразу:
Цитата
If this flag is not specified when a console process is created, both processes are attached to the same console, and there is no guarantee that the correct process will receive the input intended for it. Applications can prevent confusion by creating child processes that do not inherit handles of the input buffer, or by enabling only one child process at a time to inherit an input buffer handle while preventing the parent process from reading console input until the child has finished.
 Возможно, в ней кроется разрешение проблемы alexx83, возможно, нет.

Почему всё-таки прописываю стандартные хендлеры в STARTUPINFO, хотя эта структура должна бы иметь смысл только при создании новой консоли. 
Цитата
Important  The caller is responsible for ensuring that the standard handle fields in STARTUPINFO contain valid handle values. These fields are copied unchanged to the child process without validation, even when the dwFlags member specifies STARTF_USESTDHANDLES. Incorrect values can cause the child process to misbehave or crash.
 (взято отсюда). Возможно, в этом кроется разрешение проблемы alexx83, возможно, нет.


Цитата(boostcoder @  22.12.2012,  01:04 Найти цитируемый пост)
и чтоб по завершению родительского процесса завершался дочерний?

Никак. Дочерний процесс в огромной степени независим от родительского, если не объединять их в "задания". alexx83 очень хорошо реализовал эту схему, да, с неприятным сайд эффектом... Вполне возможно, что смерть родительского процесса каким-то образом сказывается на консоли (т.е. отсоединяет от неё дочерний процесс), к сожалению, опыта работы с такими ситуациями нет.


Цитата(alexx83 @  20.12.2012,  22:45 Найти цитируемый пост)
одно и которых при запуске меняет часть переменных среды

В принципе, если вся проблема в переменных среды, то можно как-нибудь исхитриться запускать только дочерний процесс через батник, в котором и выставлять или менять нужные переменные окружения.


А может, дело в самом экзешнике дочернего процесса, как я понял, это gdb. Возможно, это он хитро реагирует на смерть родительского процесса.

Добавлено через 4 минуты и 6 секунд
Цитата(feodorv @  22.12.2012,  05:54 Найти цитируемый пост)
If this flag is not specified

Имеется в виду CREATE_NEW_CONSOLE.

Добавлено через 10 минут и 39 секунд
Цитата(feodorv @  22.12.2012,  05:54 Найти цитируемый пост)
Никак.

Ну, в принципе, можно организовать взаимодействие через пайпы, тогда при кончине родительского процесса дочерний процесс понимает, что пайп закрылся, и можно завершаться. Но это не наш случай, у нас стандартные хендлеры не переопределяются...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
alexx83
Дата 22.12.2012, 08:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Сделал с заполнением хэндлов
Код

        memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags |= STARTF_USESTDHANDLES;
    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
    
    memset(&pi, 0, sizeof(pi));

    CreateProcess(
         0    // exe name
        ,cmdbuf    // command line
        ,0            // process security attributes
        ,0            // primary thread security attributes
        ,TRUE        // handles are NOT inherited
        ,0            // creation flags
        ,0            // use parent's environment
        ,0            // use parent's current directory
        ,&si        // STARTUPINFO pointer
        ,&pi        // receives PROCESS_INFORMATION
    );

Результат такой же как и без заполнения smile
PM MAIL   Вверх
boostcoder
Дата 22.12.2012, 23:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: нет
Всего: 110



как я понял, семейство функций exec*() работает не так как в POSIX, хотя именно для этого эти функции и предоставляются msvcrt.dll.

PM WWW   Вверх
feodorv
Дата 23.12.2012, 00:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(boostcoder @  23.12.2012,  00:27 Найти цитируемый пост)
как я понял, семейство функций exec*() работает не так как в POSIX, хотя именно для этого эти функции и предоставляются msvcrt.dll.

Многое не работает как в POSIX, а msvcrt.dll - это только лишь майкросовтовская реализация стандартной библиотеки, насколько можно приближенная к POSIX, но в общем и целом стандарту не соответствующая. Но! Майкрософт разработала специальную подсистему POSIX, в которой реализован стандарт, но в которой уже недоступны родные вызовы WinAPI.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
boostcoder
Дата 23.12.2012, 00:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: нет
Всего: 110



Цитата(feodorv @  23.12.2012,  00:08 Найти цитируемый пост)
Но! Майкрософт разработала специальную подсистему POSIX, в которой реализован стандарт, но в которой уже недоступны родные вызовы WinAPI.

это что?

PM WWW   Вверх
volatile
Дата 23.12.2012, 00:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Два раза прочитал, так и не понял, что нужно...
1.
Цитата(alexx83 @  20.12.2012,  21:45 Найти цитируемый пост)
Необходимо в идеальном случае замещать родительский процесс дочерним с сохранением взаимодействия с консолью в дочернем процессе

То есть родитель вам больше не нужен. и он может благополучно завершиться, оставив работать дочерний?
2.
Цитата(alexx83 @  21.12.2012,  19:45 Найти цитируемый пост)
нужно чтобы процессы умирали синхронно.

мысль, перпендикулярная первой smile 

Нужно чтобы висели оба, причем родитель, исключительно для того чтоы при прибивании его, прибивался и дочерний?
(больше от него проку то нет, все его функции замещены дочерним.)
Цитата(alexx83 @  20.12.2012,  21:45 Найти цитируемый пост)
Необходимо в идеальном случае замещать родительский процесс дочерним


Сформулируйте задачу четко. Тогда может и сами решите.
А пока не сформулируете чётко, ее никто не решит. (и посикс тут не причем)


Это сообщение отредактировал(а) volatile - 23.12.2012, 00:25
PM MAIL   Вверх
feodorv
Дата 23.12.2012, 00:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(volatile @  23.12.2012,  01:23 Найти цитируемый пост)
Сформулируйте задачу четко.

Нет, нет, всё понятно. Просто пытались рассмотреть разные возможности, поэтому такие несоответствия... Но всё неудачно  smile Я всё больше склоняюсь к мысли, что запускаемый экзешник - хитроватый...


Цитата(alexx83 @  22.12.2012,  09:57 Найти цитируемый пост)
Результат такой же как и без заполнения

А если всё таки запускать gdb (или что там) через bat-файл, в котором и выставлять нужные переменные окружения?


Цитата(boostcoder @  23.12.2012,  01:14 Найти цитируемый пост)
это что?

Вот это smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
volatile
Дата 23.12.2012, 00:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(feodorv @  23.12.2012,  00:38 Найти цитируемый пост)
Нет, нет, всё понятно.

Ну раз все понятно, тогда видимо я недостаточно сообразителен.
Посему, удаляюсь...

ЗЫ: Хочу сказать только, что если первое, то делал неоднократно, и все прекрасно работало.
Если второе не делал, потому как бессмысленно, но уверен что и это сделать можно.

PM MAIL   Вверх
boostcoder
Дата 23.12.2012, 01:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: нет
Всего: 110



Цитата(feodorv @  23.12.2012,  00:38 Найти цитируемый пост)
Я всё больше склоняюсь к мысли, что запускаемый экзешник - хитроватый.

ну... я хз что в нем хитрого..gdb как gdb.

Цитата(feodorv @  23.12.2012,  00:38 Найти цитируемый пост)
А если всё таки запускать gdb (или что там) через bat-файл, в котором и выставлять нужные переменные окружения?

нужно попробовать.

Цитата(volatile @  23.12.2012,  00:48 Найти цитируемый пост)
Хочу сказать только, что если первое, то делал неоднократно

а можно взглянуть на фрагмент кода?
ибо я сам проверял, и сабж невозможен. я больше склоняюсь к тому, что в вендус, вообще невозможно заменить родительский процесс дочерним.

Добавлено через 9 минут и 35 секунд
Цитата(feodorv @  23.12.2012,  00:38 Найти цитируемый пост)
Вот это

я вот только не понял, начиная с какой версии вендус предоставляется это?

PM WWW   Вверх
volatile
Дата 23.12.2012, 01:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(boostcoder @  23.12.2012,  01:02 Найти цитируемый пост)
 вендус, вообще невозможно заменить родительский процесс дочерним

boostcoder, я щас скомпилил тот код что приведен в этой теме.
в этом посте:
Цитата(alexx83 @  21.12.2012,  20:27 Найти цитируемый пост)
...
То получаю такой же результат как при использовании _execvpe, т.е. могу ввести только одну команду в консоли дочернему процессу и он отрубается от консоли 


У меня так:
Ззапускается родитель.
затем он запускает дочерний.
затем родитель завершается.
дочерний остается с той консолью, что была у родителя и полноценно работает и на ввод и на вывод.
Все пашет.

А вот зачем это
Цитата(alexx83 @  21.12.2012,  19:45 Найти цитируемый пост)
нужно чтобы процессы умирали синхронно.

мне не понять... smile 
PM MAIL   Вверх
feodorv
Дата 23.12.2012, 01:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(volatile @  23.12.2012,  01:48 Найти цитируемый пост)
тогда видимо я недостаточно сообразителен.

Это вряд ли smile 


Цитата(volatile @  23.12.2012,  01:48 Найти цитируемый пост)
Посему, удаляюсь...

Вот этого не хотелось бы... Как раз хотелось бы Вашего участия...


Цитата(volatile @  23.12.2012,  01:48 Найти цитируемый пост)
ЗЫ: Хочу сказать только, что если первое, то делал неоднократно, и все прекрасно работало.

Так и я о том же... Что-то здесь не так  smile 


Цитата(boostcoder @  23.12.2012,  02:02 Найти цитируемый пост)
ну... я хз что в нем хитрого..gdb как gdb.

Как я понимаю всё же, gdb скомпилён в GNU окружении, эмулирующем поведение UNIX. И как там сказывается эта эмуляция - я хз)))


Цитата(boostcoder @  23.12.2012,  02:02 Найти цитируемый пост)
я вот только не понял, начиная с какой версии вендус предоставляется это?

Как раз начиная с NT, какое-то там военное ведомство отказалось сертифицировать Windows NT без надлежащей поддержки POSIX. Изначально был реализован POSIX.1, сейчас число вызовов расширено (то ли 2000, то ли 3000 штук), но всё равно работа возможна только в текстовом режиме.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
volatile
Дата 23.12.2012, 01:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



В father.exe нажимаем 'f', запускается son.exe, father.exe завершаецца.
Для выхода нажимаем точку "."

father.exe
Код

#include <iostream>

void help ()
{
   std::cout << "The father ver. 1.0%s (c) xx 2012\n\n";
}

// ----------------------------------------------------------------------------------------------------------
void fork2 ()
{
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
   
   memset(&si, 0, sizeof(si));
   si.cb = sizeof(si);
   memset(&pi, 0, sizeof(pi));

   char * cmdbuf = "son.exe";
   
   CreateProcess(
       0    // exe name
       ,cmdbuf    // command line
       ,0            // process security attributes
       ,0            // primary thread security attributes
       ,0           // handles are NOT inherited
       ,0            // creation flags
       ,0            // use parent's environment
       ,0            // use parent's current directory
       ,&si        // STARTUPINFO pointer
       ,&pi        // receives PROCESS_INFORMATION
   );
       
   WaitForInputIdle(pi.hProcess, INFINITE);
       
   // free(envbuf);
   // free(resbuf);
   // free(cmdbuf);
}



// ----------------------------------------------------------------------------------------------------------
int _main ()
{
   help ();
   for (;;)
   {
       std::cout <<  "father :";
       std::string s;
       getline (std::cin, s);
       if (s == ".")
       {
          break;
       }
       if (s == "f")
       {
          fork2 ();
          break;
       }
   } 
   std::cout << ("father : --- goob bye. ---\n");
   return 0;
}

// ----------------------------------------------------------------------------------------------------------


int _tmain (int argc, tch * argv[])
{
   int ret;
   ret = _main ();
   return ret;
}


son.exe
Код

#include <iostream>

void help ()
{
   std::cout << "The son ver. 1.0%s (c) xx 2012\n\n";
}

// ----------------------------------------------------------------------------------------------------------

int _main ()
{
   help ();
   for (;;)
   {
       std::cout << "   son :";
       std::string s;
       getline (std::cin, s);
       if (s == ".")
       {
          break;
       }
   } 
   std::cout << ("   son : --- goob bye. ---\n");
   return 0;
}

// ----------------------------------------------------------------------------------------------------------


int _tmain (int argc, tch * argv[])
{
   int ret;
   ret = _main ();
   return ret;
}

user posted image

Добавлено через 1 минуту и 41 секунду
езешники father.exe, son.exe
положить в одну папку.


Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  exe_s.7z 51,93 Kb
PM MAIL   Вверх
boostcoder
Дата 23.12.2012, 01:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: нет
Всего: 110



Цитата(volatile @  23.12.2012,  01:18 Найти цитируемый пост)
Ззапускается родитель.
затем он запускает дочерний.
затем родитель завершается.
дочерний остается с той консолью, что была у родителя и полноценно работает и на ввод и на вывод.

я размышляю привычными для меня терминами.
в линукс, замещение процесса означает, загрузку другого процесса в адресное пространство первого. то, что описал ты, дает почти тот же результат. (я не говорю про наследование UID и GID)

Цитата(volatile @  23.12.2012,  01:18 Найти цитируемый пост)
А вот зачем это
Цитата(alexx83 @  21.12.2012,  19:45 )
нужно чтобы процессы умирали синхронно.

мне не понять...

это следствие того, что невозможен сабж, и приходится искать альтернативные способы достижения цели.

Цитата(feodorv @  23.12.2012,  01:25 Найти цитируемый пост)
gdb скомпилён в GNU окружении, эмулирующем поведение UNIX.

нет. gdb умеет работать в нативной вендус среде.

Цитата(feodorv @  23.12.2012,  01:25 Найти цитируемый пост)
Как раз начиная с NT, какое-то там военное ведомство отказалось сертифицировать Windows NT без надлежащей поддержки POSIX. Изначально был реализован POSIX.1, сейчас число вызовов расширено (то ли 2000, то ли 3000 штук), но всё равно работа возможна только в текстовом режиме.

странно...впервые вообще слышу о такой штуковине. посмотрел экспорт dll`ки - да, экспортируются POSIX функции.

Добавлено через 3 минуты и 44 секунды
volatile, спасибо. завтра буду проверять.
что-то уже и я запутался smile

Добавлено через 7 минут и 16 секунд
кто-то может подсказать, существуют ли вообще в открытом доступе исходники этой psxdll.dll?

PM WWW   Вверх
volatile
Дата 23.12.2012, 01:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(boostcoder @  23.12.2012,  01:50 Найти цитируемый пост)
загрузку другого процесса в адресное пространство первого.

так... этого в теме еще не было...
В таком случае это еще и 3 альтернатива, того что нужно ТС... smile

Имхо, здесь каждый говорит о своем, потому-что
Цитата(volatile @  23.12.2012,  00:23 Найти цитируемый пост)
Сформулируйте задачу четко. Тогда может и сами решите.
А пока не сформулируете чётко, ее никто не решит. (и посикс тут не причем)


PM MAIL   Вверх
boostcoder
Дата 23.12.2012, 02:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: нет
Всего: 110



ладно, пусть сформулирует...
PM WWW   Вверх
alexx83
Дата 23.12.2012, 08:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Спасибо что присоединились к этой теме volatile.

Цитата(volatile @  23.12.2012,  00:23 Найти цитируемый пост)
Сформулируйте задачу четко. Тогда может и сами решите.
А пока не сформулируете чётко, ее никто не решит. (и посикс тут не причем)

Задача проста: пишется враппер к gdb. Задача враппера изменить переменные среды и запустить gdb так чтобы он оставался привязанным к консоли в которой запущен враппер. Первый вариант - при этом враппер нам больше не нужен и он должен быть уничтожен. Второй вариант (если враппер не может быть уничтожен) - при завершении враппера должен завершаться и сам gdb.
Для примера, вы работаете в IDE и запускаете приложение на отладку. Вместо самого gdb сначала запускается враппер который потом запускает gdb. IDE ничего не знает о враппере.
По поводу вашего примера volatile. У меня от не работает как у вас на картинке smile Получаю следующее:
Код

C:\SDK\msys\toolchains\mingw64\bin>father
The father ver. 1.0%s (c) xx 2012

father :err
father :reee
father :ffddsds
father :
father :fdgrfgr
father :f
father : T-h-e-  sgoono bv ebry.e .1 .-0-%-s
 (c) xx 2012

   son :
C:\SDK\msys\toolchains\mingw64\bin>ff
   son :f
"f" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.

C:\SDK\msys\toolchains\mingw64\bin>frfr
   son :
C:\SDK\msys\toolchains\mingw64\bin>frr
   son :frfr
"frfr" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.

C:\SDK\msys\toolchains\mingw64\bin>
   son :
C:\SDK\msys\toolchains\mingw64\bin>frfr
   son :.
"." не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.

C:\SDK\msys\toolchains\mingw64\bin>.
   son : --- goob bye. ---

Может это глюк винды?
PM MAIL   Вверх
volatile
Дата 23.12.2012, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(alexx83 @  23.12.2012,  08:59 Найти цитируемый пост)
 У меня от не работает как у вас на картинке

Естественно. Это же ваш код, взятый в этой теме.
Я просто взял ваш код и показал что у меня он работает. 

alexx83, понятно, я попробую воссоздать баг, если удастся конечно. (я не пользуюсь gdb).

По крайней мере, проблема прояснилась.

PM MAIL   Вверх
boostcoder
Дата 23.12.2012, 09:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: нет
Всего: 110



volatile, вот как у меня работают тобою предкомпилированные екзешники:
user posted image

Добавлено через 11 минут и 7 секунд
win7, 64-bit.

Добавлено через 13 минут и 24 секунды
по выводу видно, что sun.exe запускается как отдельно введенная команда, а значит наследование дескрипторов не происходит.

PM WWW   Вверх
alexx83
Дата 23.12.2012, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



У boostcoder точно также работает как и у меня)) Volatile если есть возможность то вы попробуйте запустить ваши экзешники на компе без VisualStudio.
PM MAIL   Вверх
volatile
Дата 23.12.2012, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(alexx83 @  23.12.2012,  10:06 Найти цитируемый пост)
вы попробуйте запустить ваши экзешники на компе без VisualStudio

Именно так и запускал.

А вот когда запускаю из под чего-то третьего "grandfather", тогда да, получается как у вас.

Добавлено через 1 минуту и 23 секунды
alexx83, проблема понятна. будем посмотреть...

PM MAIL   Вверх
volatile
Дата 23.12.2012, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



alexx83, хорошо. Ну а с Job' ами почему у вас не работает?
Собрал фазера, опять с вашим-же кодом (тем где Job' ы), и опять у меня все прекрасно работает.
и даже из под грандфазера, и вообще из под чего-угодно....

Картинки постить не буду, уж поверьте на слово.
запускаю фазер
он запускает сына.
сидят вместе.
из менеджера закрываю фазера.
сын автоматически закрывается сам.

вот фазер, сына не менял.

Добавлено через 1 минуту и 54 секунды
вот

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  22.7z 46,06 Kb
PM MAIL   Вверх
alexx83
Дата 23.12.2012, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Да с jobами работает с одним неприятным моментом - когда завершается враппер то в консоли перед смертью gdb опять высакивает ошибка
Код

$ Exception condition detected on fd 0
error detected on stdin

PM MAIL   Вверх
volatile
Дата 23.12.2012, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



что-то интернет глючит, еще раз

Присоединённый файл ( Кол-во скачиваний: 1 )
Присоединённый файл  22.7z 46,06 Kb
PM MAIL   Вверх
alexx83
Дата 23.12.2012, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Вопрос по фазеру: 
 Почему заремили GetExitCodeProcess и "return exitCode"
PM MAIL   Вверх
volatile
Дата 23.12.2012, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(alexx83 @  23.12.2012,  14:43 Найти цитируемый пост)
 в консоли перед смертью gdb 

а что это так важно?

Имхо вообще не нужно закрывать процессы из менеждера. Это же не нормально само по себе?

Вы хотите чтоб прибивая грубо процесс из менеджера, он расшаркивался перед вами в любезностях ???
зачем?

PM MAIL   Вверх
alexx83
Дата 23.12.2012, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Цитата

Вы хотите чтоб прибивая грубо процесс из менеджера, он расшаркивался перед вами в любезностях ???
зачем?

Ну типа да должен тихо уйти с миром))
PM MAIL   Вверх
volatile
Дата 23.12.2012, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(alexx83 @  23.12.2012,  14:51 Найти цитируемый пост)
GetExitCodeProcess и "return exitCode" 

просто у меня воид функция, можете вернуть, это не принципиально

PM MAIL   Вверх
alexx83
Дата 23.12.2012, 15:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Значит пока придется использовать вариант с jobами. Большое спасибо что уделил мне время) Если вдру придет еще что-нибудь в голову обязательно запостите сюда я готов перепробовать все варианты))
PM MAIL   Вверх
volatile
Дата 23.12.2012, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



alexx83, в общем ваш вопрос сводится к несколько другой теме:
"Почему, при насильственном убиении процесса, он на что-то там успевает пожаловаться.."

Это несколько другая тема, и упирается она в очередность прибивания системой хендлов убиваемого процесса.
Воссоздать такой случай мне пока не удалось...

Гадать на расстоянии трудно, тем не менее, попробуйте следующее:
1. Добавьте также текущий процесс в Job. (Фактически у вас в Job' е только дочерний).
т.е: AssignProcessToJobObject (ghJob, GetCurrentProcess ())
(впрочем это врядли поможет).

2. Попробуйте во враппере, после создания дочернего, но перед WaitForSingleObject вставить отключение враппера от консоли.
FreeConsole ();
Возможно в таком случае убиение враппера, не будет вызывать жалобы gdb, на ошибки в stdin...

PM MAIL   Вверх
volatile
Дата 23.12.2012, 21:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(volatile @  23.12.2012,  20:26 Найти цитируемый пост)
FreeConsole ();

можно еще добавить: CloseHandle (GetStdHandle(STD_INPUT_HANDLE));
и т.д.
PM MAIL   Вверх
alexx83
Дата 23.12.2012, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Большое спасибо! Как опробую отпишусь smile
PM MAIL   Вверх
alexx83
Дата 24.12.2012, 08:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 29.3.2010

Репутация: нет
Всего: 1



Цитата(volatile @  23.12.2012,  21:07)

Цитата(volatile @  23.12.2012,  20:26 Найти цитируемый пост)
FreeConsole ();

можно еще добавить: CloseHandle (GetStdHandle(STD_INPUT_HANDLE));
и т.д.

Танцев с бубнами не понадобилось. Ошибки при снятии процесса куда-то ушла)
Всем спасибо за обсуждение. Считаю тему закрытой.
PM MAIL   Вверх
volatile
Дата 24.12.2012, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(alexx83 @  24.12.2012,  08:12 Найти цитируемый пост)
Ошибки при снятии процесса куда-то ушла

бывает...  smile 
PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.2066 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.