Определить, выполняется ли сценарий Tcl в фоновом режиме - PullRequest
1 голос
/ 30 мая 2020

Я ищу желательно кроссплатформенный способ определить из сценария Tcl, работает ли интерпретатор на переднем плане или в фоновом процессе.

Я видел, как это сделать через ps (или /proc/$$/stat на Linux); есть ли лучший способ, или мне нужно что-то взломать вокруг этого подхода? У меня уже есть служебная библиотека, написанная на C, поэтому можно было бы раскрыть API низкого уровня, который также использует ps, чтобы мне не приходилось анализировать вывод процесса (или особое содержимое файла).

Ответы [ 2 ]

1 голос
/ 30 мая 2020

По-настоящему кроссплатформенного понятия переднего плана нет, но на основных платформах есть способы сделать это в соответствии с представлением, которое у них есть переднего плана .

Linux, macOS, и другие Unix:

Для определения того, является ли процесс приоритетным или нет, вам необходимо проверить, является ли его идентификатор группы процессов идентификатором управляющей группы процессов терминала. Что касается Tcl, вы должны увидеть системные вызовы getpgrp() и tcgetpgrp() (оба POSIX). Tcl не имеет встроенного представления ни того, ни другого, поэтому вы говорите либо о скомпилированном расширении (могу ли я порекомендовать Critcl для этого?), Либо о вызове внешней программы, например ps. К счастью, если вы используете последнее (разумный вариант, если это всего лишь случайная операция), вы, как правило, можете подготовить вывод так, чтобы вы получали только ту информацию, которая вам нужна, и вам не нужно ее анализировать. 1016 *Windows

Для этого есть код , а необходимые вызовы поддерживаются расширением TWAPI , поэтому вам не нужно создавать свой собственный. (ВНИМАНИЕ! Я это не тестировал!)

package require twapi_ui

proc isForeground {{pid 0}} {
    set forground_pid [get_window_thread [get_foreground_window]]
    return [expr {($pid ? $pid : [pid]) == $foreground_pid}]
}
0 голосов
/ 30 мая 2020

Благодаря Доналу я придумал реализацию ниже, которая должна работать на всех вариантах POSIX Unix:

/*
    processIsForeground

    synopsis: processIsForeground

    Returns true if the process is running in the foreground or false
    if in the background.
*/
int IsProcessForegroundCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
    /* Check the arg count */
    if (objc != 1) {
        Tcl_WrongNumArgs(interp, 1, objv, NULL);
        return TCL_ERROR;
    }

    int fd;
    errno = 0;
    if ((fd = open("/dev/tty", O_RDONLY)) != -1) {
        const pid_t pgrp = getpgrp();
        const pid_t tcpgrp = tcgetpgrp(fd);
        if (pgrp != -1 && tcpgrp != -1) {
            Tcl_SetObjResult(interp, Tcl_NewBooleanObj(pgrp == tcpgrp));
            close(fd);
            return TCL_OK;
        }
        close(fd);
    }
    Tcl_SetErrno(errno);
    Tcl_ResetResult(interp);
    Tcl_AppendResult(interp, "processIsForeground: ", (char *)Tcl_PosixError(interp), NULL);
    return TCL_ERROR;
}

int Pextlib_Init(Tcl_Interp *interp)
{
    if (Tcl_InitStubs(interp, "8.4", 0) == NULL)
        return TCL_ERROR;
// SNIP
    Tcl_CreateObjCommand(interp, "processIsForeground", IsProcessForegroundCmd, NULL, NULL);

    if (Tcl_PkgProvide(interp, "Pextlib", "1.0") != TCL_OK)
        return TCL_ERROR;

    return TCL_OK;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...