LINUX.ORG.RU

Избранные сообщения POLTER

Нюансы запуска процессов через system/exec

Форум — Development

Случай #1:

Как известно, при вызове exec происходит завершение всех нитей вызывающего кроме той, что вызвала system. При этом открытые дескрипторы клонируются в новый процесс (если у них не указан флаг FD/SOCK_CLOEXEC).

Представим следующую гипотетическую ситуацию:

У нас есть некая программа, которая получает от кого-то строку, в которой содержатся какие-то команды, которые нужно запустить. Пусть, к примеру, это будет какое-то подобие супервизора.

Положим, что так как эта строка может содержать переменные среды, какие-то выражения подстановки и shell-related команды и синтаксис программист, написавший эту программу посчитал, что самым оптимальным образом будет запускать эту строку с помощью команды system, которая не требует списка аргументов, как семейство exec*. Плюс, так как system «под капотом» вызывает sh -c ..., то автоматически подставятся переменные, а shell-related команды и синтаксис будут работать как нужно. Так вот, глянем исходник system, например, для glibc:

<Сначала хотел показать исходник glibc, но тут слишком дофига получается кода, поэтому сжато: clone + exec + waitpid, кстати ман говорит про fork + exec + waitpid, что не совсем то же самое>

При вызове clone/fork происходит копирование открытых дескрипторов, которые наследует процесс, который запустил system. Предположим, что кто-то передал для запуска строку, содержащую запуск программы (назовем ее evil), выполняющей следующие действия:

if (fork() != 0)
    exit(0);

Что превращает ее в отвязанного от родителя демона. Однако этот fork тоже наследует все открытые хэндлеры, что приводит нас к тому, что этот демонутый процесс evil получил копию всех открытых хендлеров супервизора, однако стал от него отвязан (system вернул 0, супервизор считает, что работа выполнена).

Теперь предположим, что это супервизор с управлением по сети. То есть супервизор открывает серверный сокет и слушает команды, которые ему приходят извне. Не будем обсуждать защищенность передачи или канала связи, всё можно сломать, суть сейчас не в этом. Суть в том, что на момент запуска system супервизор владел открытым серверным сокетом (!). Да, по совести и по правилам при его создании ему нужно было выставить SOCK_CLOEXEC, но скажем честно, кто своим серверным сокетам выставляет флаг, о котором даже в мануалах на socket из 153 строк отдано 2 (!), т.е. всего 1.3%?

Таким образом, пройдя через всю цепочку форков копия серверного сокета оказывается у демонутого evil:

super      9053 alex    3u  IPv4 11458560      0t0  TCP *:34002 (LISTEN)
super      9053 alex    4u  IPv4 11464960      0t0  TCP localhost:34002->localhost:41308 (ESTABLISHED)
evil       9257 alex    3u  IPv4 11458560      0t0  TCP *:34002 (LISTEN)

Положим, что процесс супервизора по какой-то причине завершился. Ну, например, выполнив свою работу или по ошибке. И теперь начинается самая мякотка. Ведь в системе уже открыт слушающий на порту 34002 сокет! И принадлежит он программе evil! Таким образом она может прикинуться сервером, а супервизор, в свою очередь, не сможет вернуть свой сокет, поэтому система не даст ему открыть второй сокет на том же порту без REUSEPORT:

SO_REUSEPORT (since Linux 3.9)
              Permits multiple AF_INET or AF_INET6 sockets to be bound to an identical socket address.  This option must be set on each socket (including the first socket) prior to calling bind(2) on the socket.  To prevent port hijacking, all of  the  pro‐
              cesses binding to the same address must have the same effective UID.  This option can be employed with both TCP and UDP sockets.

В общем случае, когда какая-то программа-сервер запускается и получает ALREADYINUSE то надо бы сказать мол, «не не могу работать, наверное другая копия меня уже запущена» и выключиться (ну или ожидать его освобождения).

Мы же не хотим port hijacking, верно? А вот все равно профукали. Ну и теперь evil может делать что угодно. Может получать данные от клиентов, может им даже что-то отвечать,может получать список команд для запуска и запускать вместо них что угодно, сообщая наверх что всё хорошо.

Собственно, вопрос #1: почему на серверный сокет автоматически при создании не вешается FD_CLOEXEC?

Случай #2:

Мы - супервизор, запускающий программы, забудем про сетевое взаимодействие, мы сами знаем, что нам запускать. Запускают нас от root, для того, чтобы мы могли делать какую-то очень важную вещь, ну, например, читать какой-то root-owned файл:

-rw-------  1 root root        7 июн  5 23:51 rootonly

Изобразим супервизор упрощенно:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>       
#include <sys/wait.h>
#include <errno.h>       
#include <pwd.h>


static void dowork(void) {
    int pid = fork();
    int status;
    switch (pid) {
        case -1 : exit(EXIT_FAILURE);
        case 0  :
            if (setuid(1000) == -1) {
                printf("u:%u\n", errno);
            }
            if (seteuid(1000) == -1) {
                printf("e:%u\n", errno);
            }
            execl("./hijack_evil.elf", "./hijack_evil.elf", NULL);
            printf("cannot run\n");
            exit(EXIT_FAILURE);
        default :
            wait(&status);
    }
}

int main(void) {
    FILE * fileroot = fopen("/tmp/rootonly", "r");
    printf("I am %s, #%u/%u\n", getpwuid(getuid())->pw_name, geteuid(), getuid());
    
    dowork();
    
    fclose(fileroot);
    return 0;
}
gcc hijack_root.c -o hijack_root.elf

И программу, которой нельзя давать рутовые права:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>       
#include <sys/wait.h>
#include <pwd.h>

int main(void) {
    printf("I am %s, #%u/%u\n", getpwuid(getuid())->pw_name, geteuid(), getuid());
    // my stdin is 0, stdout is 1, stderr is 2, therefore...
    char buf[1024];
    read(3, buf, 1024);
    printf("%s\n", buf);
    return 0;
}
gcc hijack_evil.c -o hijack_evil.elf

Проверяем, что просто так файл прочитать нельзя:

alex@ThinkPad-L560:~$ cat /tmp/rootonly 
cat: /tmp/rootonly: Отказано в доступе
alex@ThinkPad-L560:~$ echo $USER/$UID
alex/1000

И запускаем супервизор:

$ sudo ./hijack_root.elf 
I am root, #0/0
I am alex, #1000/1000
SECRET

При этом мы не можем ставить FD_CLOEXEC на каждый хендлер, открываемый в супервизоре, потому что он может понадобиться для целей супервизора в его форках. Соответственно вопрос #2: почему внешние программы, запускаемые через exec наследуют хендлеры? Ведь очевидно, что это может быть использовано только для «угона» файлов

 ,

PPP328 ()

Intel AX200 как точка доступа

Форум — Linux-hardware

Смотрю на вот это вот чудо и хочу понять, будет ли оно работать как точка доступа в 5 ГГц диапазоне.

Есть такой зверь у кого? Поделитесь выводом iw list.

Ну и чтобы два раза не вставать — что вообще сейчас нужно брать и ставить в PCI-E, чтобы сделать как минимум 802.11ac (а ещё лучше ax)?

 , , , ,

post-factum ()

Дождливый XMonad

Галерея — Скриншоты

Терминал — urxvt, бар — polybar

Конфиги: https://github.com/malyutinegor/rainy

Видео с обоями: https://i.imgur.com/CTiwPki.mp4 (они обычно всегда отключены, включаю чисто чтобы помедитировать)

>>> Просмотр (1366x768, 752 Kb)

 , , , ,

rk-d ()

Как понять, отчего программа тормозит?

Форум — General

Иногда у меня сильно тормозят некоторые программы (chrome/chromium, файловые менеджеры на разных тулкитах и даже gvim иногда). Иногда я подключаюсь к программе при помощи strace и пытаюсь понять, в чём причина тормозов. Как правило, безуспешно — мне не хватает базовых знаний (я не программист).

Вопрос: что (кроме man strace) нужно знать для поиска тормозов ПО?

Можете накидать годных ссылок на описание процесса решения проблем при помощи strace (и другого ПО)?

 

Harliff ()

Что-то странное с кэшем в Linux-дистрибутивах

Форум — General

Я не знаю, как вы, но я давно заметил, что некоторые дистрибутивы (Ubuntu, Fedora, Linux Mint) не умеют обращаться с кэшем памяти. Я не шибко знаток этой темы, но кэш просто заполняется до отказа, пока система не фризится жёстко (только перезагрузка помогает). Есть ли хотя бы какие-то вменяемые костыли, чтобы это не происходило? Знаю про решение с освобождением кэша командой «sudo sync; echo 3 > /proc/sys/vm/drop_caches», но оно настолько костыльное, что просто ощущаешь себя реальным инвалидом.

Решение

Не рекомендую делать реиндексацию. Комп тупо не справится (у меня 8 ядер, 16 Гб ОЗУ - не потянул). Проще скачать блокчейн заново.

 , , , ,

Desmond_Hume ()

Объясните сишную магию

Форум — Development

Пытался понять как реализовать SVG фильтр feComposite, ибо SVG дока унылая, поэтому залез в сорцы вебкита. Там тоже документации ноль, ещё и код очень странный.

Вот что это за ужас (src):

static unsigned char clampByte(int c)
{
    unsigned char buff[] = { static_cast<unsigned char>(c), 255, 0 };
    unsigned uc = static_cast<unsigned>(c);
    return buff[!!(uc & ~0xff) + !!(uc & ~(~0u >> 1))];
}

Я так понимаю, они проверяют что int в 0..255 диапазоне, но уж слишком странным образом.

UPD: коммит, который добавил этот код.

 ,

RazrFalcon ()

Документация к языкам программирования

Форум — Development

Всевозможные учебники и книги - это хорошо, но обычно их предлагают купить и часто не совсем дёшево, даже если они описывают базовый уровень. Бесплатным решением, очевидно, является официальная документация. Когда я открыл документацию к python, я был приятно удивлён, что она написана практически как учебник. Для Java вроде бы тоже всё относительно неплохо в этом плане, хотя хотелось бы отдельный оффлайновый pdf.

Мне захотелось скачать себе документацию в подобном виде для C и C++. Зашёл на их официальные сайты, там описание стандарта предлагают получить на сайте ISO за немалые суммы денег. Да и само описание стандарта далеко не для обучения. Хорошо, подумал я, попробую тогда посмотреть документацию к одной из реализаций языка - GCC-CPP, и вижу, что описанное там тоже вовсе не подходит для обучения. Даже описания типов и примеров объявления нет (может плохо искал, но в заголовках не заметил).

Нет, это не тред «подскажите книгу по Сям», таких для начинающих я и сам могу гору насоветовать.

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


Update

C, C++
Online-ресурсы и учебные пособия для начинающих:

Как дополнение: Рабочая версия стандарта C++14 от 19 ноября 2014 г. (с официального сайта стандарта)


Fortran


Python
В дополнение к официальной документациипереводу руководства Python 3.1):


Object Pascal. Lazarus

Перемещено Klymedy из talks

 , , , ,

grem ()

Осиливаем DXVK в вайн, запуск любых DX11 игр в вайн без тормозов

Форум — Games

0. последние драйвера нвидии (пользователям АМД земля пухом)
1. Ставим ОБЫЧНЫЙ(НЕ СТАГИНГ) wine-3.7
2. Идем сюда https://github.com/doitsujin/dxvk/releases/tag/v0.50
3. качаем dxvk-0.50.tar.gz
4. запускаем (объявив вайн префикс если нужно) x64 или x32 в зависимости от вайна setup_dxvk.sh

ВСЕ РАБОТАЕТ ничего больше делать не нужно

если ФПС СЛИШКОМ НИЗКИЙ:
запускать с
__GL_NextGenCompiler=0

Что еще может быть причной НИЗКОГО ФПСА

Вайн без «эмуляции рабочего стола» и «оконный режим» игры, ФПС будет очень низкий, поставьте «эмуляцию рабочего стола» в настройке Вайн

(дальше специфические проблемы, редко возникают и почти незаметныы)
Ваш ДЕ конфликтует с Вулканом, я встречал это на XFCE(вплоть до зависания иксов) где ФПС до 50% ниже чем OpenGL
(на чистых иксах ФПС в вулкане ниже чем в гноме3)
предполагаю множество проблем в «минималистичных DE» где рендеринг непонятно как сделан
в Gnome3 в вулканом нет никаких проблем

другие программы использующие иксы/vdpau/opengl
запуск «некоторых» шейдеров в OpenGL паралельно Вулкану будет давать стабильный краш вулкана
хром со включенным видео на сайте, одновремено видеоплеер использующий vdpau, вулкан будет рандомно крашиться
после использования NVENC вулкан может либо не стартовать вообще либо ФПС упадет в десятки раз
Thunderbird очень силько конфликтует с вулканом по какойто причине(даже закрытый в трее без окна)
...и прочее, лучше закрыть все перед запуском

 , ,

missxu ()

Конспект по GNU Make

Форум — Development

Привет, я штудировал доки по Make (уже второй раз за несколько лет) и пожалел о том, что в прошлый раз не составил небольшой конспект. Оставлю здесь на случай, когда потребуется освежить память, может и ещё кто сочтёт полезным.

1.  include / -include - включить Makefile, дупускаются shell
    шаблоны. С / без ошибки при отсутствии файла. После прочтения всего
    Makefile, имена файлов, которые указаны  директиве, проверяются на
    возможность обновления рецептами. В случае обновления включаются
    заново (основа для автоматической генерации зависимостей).

2.  Secondary expansion - после чтения Makefile и перед фазой
    обновления целей, производится второй проход по списку
    пререквизитов. Доступны автоматические переменные.
        .SECONDEXPANSION:
        main_OBJS := main.o try.o test.o
        lib_OBJS := lib.o api.o
        main lib: $$($$@_OBJS)

3.  Order-only пререквизиты - цель не будет считаться устаревшей при
    выполнении рецепта такого пререквизита
        targets : normal_prereq | order_only_prereq.

4.  Переменная VPATH - пути поиска всего. Директива vpath - пути поиска
    для определённого класса файлов.

5.  .PHONY : target - цель target всегда устаревшая. Для target не
    производится поиск неявных правил.

6.  Если в качестве пререквизита -lname, то поиск библиотеки в
    следующих местах: в текущей директории, vpath и VPATH, /lib,
    /usr/lib, prefix/lib.

7.  Если существуют несколько правил с одним двоеточием для одной цели,
    то все они объединяются в одно правило. Рецепт может быть указан
    лишь однажды, если его нет, то поиск среди неявных правил.

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

9.  target : ; пустой рецепт, не будет производиться поиск неявного
    правила.

10. Static pattern rule
       targets : target-pattern : prereq-pattern
            recipe
       ${objects} : %.o : %.c
    Часть имени соответствующая % - stem.

11. Каждая строка рецепта исполняется в своей shell (в одной есле
    .ONESHELL). Shell, которая используется, хранится в SHELL, опции в
    .SHELLFLAGS. Значение SHELL не наследуется из окружения make.
    Exit-status shell, выполняющей команду, содержится в .SHELLSTATUS.

12. В рецепте (в начале строки):
       @ - отключает печать команды (-n и --just-print всё равно
           печатают такие команды);
       + - выполнить даже если заданы -n или --just-print;
       - - игнорировать ошибки при исполнении команды.

13. В рецепте: обращение к make переменной ${var}, к shell переменной
    $${var}.

14. При рекурсивном вызове make использовать переменную ${MAKE}
       $(MAKE) -C subdir

15. [override] undefine var - удалить переменную.

16. export / unexport var [=val] - экспортировать / не экспортировать
    переменную в sub-make. Одинокий export / unexport - экспортировать
    / не экспортировать все переменные.

17. var = val - ссылка;
    var := val - обычная переменная;
    var += val - ссылка ли, зависит от типа val;
    var ?= val - присвоить значение если var не объявлена;
    var != cmd - выполнить cmd в shell;
    ${foo:.o=.c} - заменить .o в конце слов на .c;
    ${foo:%.o=%.c}

18. Иерархия переменных:
       1. объявлянные внутри Makefile с override (дальнейшая
          модификация возможно только с override);
       2. переданные через командную строку;
       3. объявленные внутри Makefile без override;
       4. из окружения, где запускается make.
    Экспортируются переменные в sub-make:
       1. из окружения, где запускается make (редактирование внутри
          Makefile не влияет);
       2. переданные через командную строку (если Makefile редактирует
          с override, то в sub-make приходит значение из командной
          строки);
       3. объявленные внутри Makefile с export.

19. MAKEFLAGS - содержит флаги переданные при запуске make +
    переменные со значениями переданными через командрую строку, но не
    содержит цели. В переменную можно добавить флаги внутри Makefile
    или в окружении, в котором запускается make).

20. MAKELEVEL - содержит целое число, которое указывает на глубину
    рекурсии. 0 для главного make.

21. MAKECMDGOALS - содержит цели заданные при запуске make.

22. Target-specific переменные
       prog : [private] CFLAGS=-g
       prog : prog.o foo.o bar.o
           recipe
     задаёт CFLAGS в рецептах для prog, prog.o, foo.o, bar.o. Если
     private стоит, то пререквизиты не наследуют CFLAGS. Если
     переменная объявлена private на глобальном уровне, то она не
     будет видна ни в одно рецепте.

23. Pattern-specific переменные
       %.o : CFLAGS=-g

24. Match-anything pattern rule (цель одинокий %). Бывают:
      1. терминальные (%::pregeq) - prereq должен существовать, не
         может быть создан посредством другого правила.
      2. иначе - правило будет рассмотрено только если нет других
         неявных правил , чья цель совпадает с искомой.

25. Last-resort default rule
      1. %::
      2. .DEFAULT:      # если рецепт не указан, то текущее правило
                          будет удалено

26. Отмена неявного правила
       %.o:%.s
    указать ту же цель и те же пререквизиты, рецепт не указывать.
    
27. Архивы:
      1. при использовании нотации со скобками ( libname(objs) ) не
         допускать параллельного запуска make (-j опция).
      2. внутри архива содержится таблица символов (__.SYMDEF), ranlib
         lib.a её обновляет. GNU ar не требует запуска вручную,
         запускает её автоматически.

28. Договорённости:
      * Каждый Makefile должен содержать
          SHELL = /bin/sh
        для избежания проблем на системах, где SHELL может быть
        унаследована из окружения.
        
      * Не плохо задать суффиксы для которых будет производиться поиск
        неявных правил
           .SUFFIXES:             # удаляет все раннее установленные
           .SUFFIXES: .c .o
           
      * ar bison cc flex install ld ldconfig lex make makeinfo ranlib
        texi2dvi yacc chgrp chmod chown mknod - вызывать через
        переменные ${AR}, ... . Для каждой переменной-команды
        переменная с опциями образуется добавлением FLAGS к имени
        (исключение - CFLAGS, YFLAGS, LFLAGS).

       * команды, которые следует использовать напраямую (без
         переменных): awk cat cmp cp diff echo egrep expr false grep
         install-info ln ls mkdir mv printf pwd rm rmdir sed sleep
         sort tar test touch tr true gzip.

       * каждый Makefile должен задавать переменные: INSTALL,
         INSTALL_PROGRAM (дефолтно ${INSTALL}), INSTALL_DATA (дефолтно
         ${INSTALL} -m 644).

       * staged install - для целей install и uninstall поддерживать
         переменную DESTDIR
            $(INSTALL_PROGRAM) foo $(DESTDIR)$(bindir)/foo
            $(INSTALL_DATA) libfoo.a $(DESTDIR)$(libdir)/libfoo.a

       * установка info и man страниц в цели install.

       * Разбивка install на $(PRE_INSTALL), $(POST_INSTALL),
         $(NORMAL_INSTALL). Разбивка uninstall на $(PRE_UNINSTALL),
         $(POST_UNINSTALL), $(NORMAL_UNINSTALL).

Господа, у меня вот ещё какой вопрос имеется: вот написал я какую-нибудь софтину, как мне определиться с именами файлов и всего проекта? Т.е. чтобы небыло конфликтов имён с другим софтом при make install. К тому же если сегодня конфликтов нет, то завтра у меня нет никаких гарантий, что такой софт не появится. Как тут правильно поступать? Каждый проект должен писать какие-то проверки на конфликты имён? Если так, то делает ли это автоматом autoconf+automake? cmake?

 

pavlick ()

Хранение паролей

Форум — Security

Здравствуйте.

Паролей от всевозможных аккаунтов становится все больше и больше, в связи с этим назрел вопрос об их хранении. Подскажите пожалуйста, есть ли какой нибудь сервер(soft) для централизованного хранения и доступа к нему с разных устройств? Менеджеры паролей не устраивают, т.к. неудобно разбрасывать базу между несколькими устройствами и пользователями.

 ,

torm7 ()

Курс по компиляторам

Форум — Development

В 14-м году на курсере был классный курс, который я упустил. А сейчас понял что очень хочется его пройти. После гуглежа оказалось, что курс доступен бесплатно без смс прямо на сайте стенфорда.

Вот, выкладываю ссылку (может будет полезно кому-нибудь) https://lagunita.stanford.edu/courses/Engineering/Compilers/Fall2014/

Если есть ещё слоупоки кроме меня, то давайте вместе проходить!

 , ,

dsxl ()

очень хочется поделиться ))

Форум — Development

хук на бранч, gitlab vs jenkins

1. в дженкинсе наплодить джобиков (dev, test, master) и на каждый ждобик выставить галку Trigger builds remotely (e.g., from scripts). написать туда ключик, всем разные.

2. добавить в корень проекта .gitlab-ci.yml типа такого:

stages:
- build_developer
- build_test
- build_master



build_developer_job:
  stage: build_developer
  only:
  - develop
  script:
  - curl http://jenkins.url/job/project-develop/build?token=token_develop



build_test_job:
  stage: build_test
  only:
  - test
  script:
  - curl http://jenkins.url/job/project-test/build?token=token_test



build_master_job:
  stage: build_master
  only:
  - master
  script:
  - curl http://jenkins.url/job/project-master/build?token=token_master

ну и конечно добавить раннер: https://docs.gitlab.com/runner/register/index.html

и волосы будут здоровые и шелковистые.

может это просто и все знают, но у меня прям локальная победа :)

 ,

Rastafarra ()

Debian 9 Stretch + dwm

Галерея — Скриншоты

Достался мне для ремонта нетбук Acer Aspire One D255 c 1GB RAM на борту.

Поменял порванную WiFi-антенну и корпус (по счастливому стечению обстоятельвств нашел на avito за копейки), заменил планку памяти на 2GB.

Ранее установленный и работающий отнюдь не быстро на таком железе Linux Mint 17 с XFCE решил заменить на Debian 9 Stretch с dwm 6.1.

Установил с netinstall-образа со всеми необходимыми компонентами, задействовал zswap c lz4/zsmalloc, дисплейный менеджер не используется - работает автовход в сессию иксов.

Cобрал dwm с учетом патчей:

dwm-resizecorners-6.1.diff
dwm-fancybar-6.1.diff
dwm-pertag-6.1.diff
dwm-6.1-save_floats.diff
dwm-6.1-systray.diff
dwm-attachaside-6.1.diff
dwm-push-6.1.diff
dwm-r1615-selfrestart.diff

Шрифты: в системе и в панели - Cantarell 9, Font Awesome 9 для значков тегов, в терминале - Ubuntu Mono 10.

Терминал - urxvt, текстовый редактор - geany, файловый менеджер - PCmanFM.

GTK Theme - Espresso 0.1 (модифицированная), иконки - Vivacious-NonMono-Light-Yellow.

Скриншоты: PCmanFM+SMPlayer, Geany, PaleMoon+LOR.

>>> Просмотр (1024x600, 920 Kb)

 ,

mad_austronaut ()

Совместное использование ресурсов

Форум — Development

Есть проблема доступа к совместным ресурсам. Я вот не пойму, это реальная проблема, или она надумана?

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

Пусть есть условная ячейка памяти, которую разные процессы могут инкрементить. Как принято представлять эту модель? Процесс №1 считывает текущее значение из памяти(допустим - это 0), прибавляет к нему единицу, а затем записывает в память получившееся значение вместо предыдущего. Соответственно пока процесс №1 производит операцию сложения, процесс №2 может считать значение памяти, и начать свою операцию сложения. Затем, после того как процесс №1 записал результат(1) в память, процесс № 2 также записывает свой результат(1) в память, и результат 2-х инкрементов — 1.

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

Это все выглядит уродливо, как кровавое месиво.

Давайте посмотрим на это с другой стороны.

Есть условная ячейка, к которой имеет доступ только один процесс, который умеет ее инкрементить. Остальные процессы могут послать сообщения этому процессу, с «просьбой» инкрементации. При этом, эти мессенджеры абстрагированны от текущего значения счетчика, нет нужды считывать значения и производить собственные операции над этим значением, их дело — послать собщение и все. Они не имеют никакого доступа к этой памяти.

То есть, обычная инкапсуляция. И нет никакой проблемы.

Если это так просто, то зачем городить огород? Зачем решать несуществующие проблемы? Может это выгодно всякого рода горе-дезигнерам, делать вид, что существует проблема, нет проблемы — нет и хлебушка с маслицем?

Перемещено tailgunner из development

Перемещено jollheef из job

 , ,

vikingfilmtracker ()

Убираю status bar. Всё перекрашивается в странные цвета.

Форум — Development

Задача: убрать status bar и ничего не сломать.
Нюанс: Использую Qt, поэтому могу это сделать лишь из Manifest.xml.
Итого прописываю:

android:theme="@android:style/Theme.NoActionBar.Fullscreen"

Получаю: status bar действительно скрывается, но цвета плывут. Похоже на то, что Андроид мне подсовывает какую-то тёмную тему. А я хочу чтобы он просто никуда не лез и ничего не трогал, а просто убрал то, что приказано.
В общем что мне делать?

 ,

Stahl ()

PIMPL без указателя

Форум — Development

Всем хорошо известен паттерн PIMPL через скрытие реализации за указателем. С известными же проблемами неоптимального исполнения, когда нужно дополнительно аллоцировать память под сам указатель. Сходу нашёл в интернете варианты вместо указателя использовать заранее большой массив, на котором вызывается placement new, но такой подход вызывает ещё больше вопросов.

В самом C++ для скрытия реализации есть абстрактные интерфейсы без данных, реализация которых создаётся через фабрику или статический метод вместо конструктора. Однако с абстрактными интерфейсами одна беда — если наследовать один интерфейс от другого, то их реализации будут иметь ромбовидное наследование — один раз от наследуемого интерфейса, второй раз от реализации базового интерфейса. Ложку дёгтя добавляет необходимость замены конструкторов фабриками и руками делать правильные вызовы родительских конструкторов. Добавим сюда необходимость писать для каждого класса фактически два: один обстрактный, второй с реализацией. Получим достаточно неудобный подход, недостатки которого устраняет PIMPL.

Возьмём к примеру библиотеку Qt, объектная модель которой полностью построена на PIMPL и наследовании от базового QObject. При этом сами объекты на стеке или по значению создаются крайне редко, в повальном случае экземпляры QObject выделяются в куче. Получаем двойную аллокацию: первую для самого указателя, вторую для данных по указателю. Также при использовании подобных экземпляров будет двойное разименование, что также негативно скажется на производительности. При этом подсознательно понимаешь, что подобный подход бессмысленнен, ведь PIMPL-указатель никогда не подменяет реализацию на этапе выполнения, он создаётся исключительно в конструкторе и удаляется исключительно в деструкторе объекта.

А что если вообще без указателя и данных в интерфейсе? Вместо дополнительного указателя на данные использовать указатель на интерфейс. Аллокацию же переопределять операторами new и delete.

Вот простой пример, нарисованный на коленке:

#pragma once

#include <cstddef>

class A
{
public:
	A(int value = 42);

	int value() const;
	void setValue(int value);

	DECLARE_PRIVATE(A)
};

class B : public A
{
public:
	B(int data);

	int data() const;

	DECLARE_PRIVATE(B)
};
#include "lib.h"

class A::Private
{
public:
	int value;
};
DEFINE_PRIVATE(A)

A::A(const int value)
{
	to_private()->value = value;
}

int A::value() const
{
	return to_private()->value;
}

void A::setValue(const int value)
{
	to_private()->value = value;
}


class B::Private : public A::Private
{
public:
	int data;
};
DEFINE_PRIVATE(B)

B::B(const int data)
{
	to_private()->data = data;
}

int B::data() const
{
	return to_private()->data;
}

DECLARE_PRIVATE и DEFINE_PRIVATE переопределяют операторы new и delete и определяют методы приведения реализации к интерфейсу:

#define DECLARE_PRIVATE(T) \
public: \
	void * operator new(std::size_t size); \
	void operator delete(void * ptr); \
	class Private; \
private: \
	const Private * to_private() const { return reinterpret_cast<const Private*>(this); } \
	Private * to_private() { return reinterpret_cast<Private*>(this); }

#define DEFINE_PRIVATE(T) \
	void * T::operator new(const std::size_t size) \
	{ \
		return new Private; \
	} \
	\
	void T::operator delete(void * const ptr) \
	{ \
		delete static_cast<Private*>(ptr); \
	}

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

std::unique_ptr<B> b(new B(95));
b->setValue(33);

Сравним с традиционным подходом в Qt:

  • Объявление класса: Qt — Q_DECLARE_PRIVATE(classname), в нашем случае то же самое — DECLARE_PRIVATE(classname).
  • Определение класса: Qt — наследование реализации, то же самое у нас + DEFINE_PRIVATE(classname).
  • Аллокация класса: Qt — явный вызов базового класса с передачей указателя на реализацию
    MyObject::MyObject() : MyParentObject(*new MyObjectPrivate)
    у нас — неявный вызов базового класса без лишних телодвижений.
  • Обращение к реализации: Qt — d_func(), у нас — to_private().
  • Аллокация объекта в куче: Qt — две аллокации, в нашем случае — одна.
  • Аллокация объекта на стеке: Qt — одна аллокация, в нашем случае тоже одна, через явный operator new.

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

Я догадываюсь, что всё выше есть велосипед, но почему-то я нигде не встречал подобной реализации (кроме исходников Андроида). Собственно, какие у есть минусы у данного подхода? Какие известные проекты практикуют подобный подход вместо традиционного PIMPL?

 

Dendy ()

Есть ли лоровцы, заинтересованные в продолжении развития QtWebKit?

Форум — Development

В частности, имею в виду переход на современную версию движка.

 , ,

annulen ()

Игровые сервера L.O.R.

Форум — Games

Благодаря Вкусносерверу у нас есть сервера, где можно собраться и поиграть.
Запущено:

  • UT2004, dm;
  • teeworlds - instagib/vanilla;
  • Openarena;
  • Warsow.

На очереди к запуску:

  • Openttd;
  • Xonotic;
  • Hedgewars.


Маленькая просьба: добавляйте к нику [Lor], чтобы мы могли друг друга узнавать :)

Списки запущенных серверов:

ut2004, dm, deck17 (maprotate автоматический, карты дефолт). Версия игры должна быть 3369, то есть последняя. Для коннекта используем либо tazhate.ru, либо 217.73.58.123, либо 217.73.56.129. Настраиваем ник/скин игрока в settings и прочее, что надо, потом вызываем консоль по ~, пишем туда open 217.73.58.123. Должно подключиться.

teeworlds instagib, maprotate по стандартным картам + пара веселых, версия должна быть 0.6.1. Искать по поиску (сняв все галки справа) по словам linux либо lor. Либо коннектитесь напрямую, любой из айпи выше + порт 8303.

teeworlds vanilla, maprotate по стандартным картам + пара веселых, версия должна быть 0.6.1. Искать по поиску (сняв все галки справа) по словам linux либо lor. Либо коннектитесь напрямую, любой из айпи выше + порт 8304.
Модератор обоих серверов teeworlds - z00ke, для киков/банов каких-нибудь гуманоидов обращайтесь к нему.

Облегчаю себе (и другим) касту:
Играющие в ut2004:

[user]tazhate[/user], [user]Spirit_of_Stallman[/user],[user]nihil[/user],[user]Gary[/user], [user]Worron[/user], [user]kostian[/user], [user]tekk[/user],[user]DrF[/user],[user]Darth_Revan[/user], [user]abyz[/user],[user]lorovec[/user], [user]LinuxUser[/user],[user]stevejobs[/user]

Играющие в teeworlds:
[user]tazhate[/user], [user]z00ke[/user],[user]ei-grad [/user], [user]nickionn[/user], [user]HunOL[/user], [user]dikiy[/user], [user]Paused[/user], [user]aidan[/user], [user]i_gnatenko_brain[/user],[user]stevejobs[/user]

Играющие в Openarena:
[user]tazhate[/user],[user]stevejobs[/user]
Играющие в Warsow:
[user]tazhate[/user],[user]gavlig[/user],[user]santic[/user],[user]stevejobs[/user]
Если кто хочет в список - просите добавить в комментариях.


ps: игры не нужны, да.
pps: для minetest|minecraft есть http://ttyh.ru

 ,

tazhate ()

О чем вы говорите, кроме как о делах?

Форум — Talks

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

И что характерно, я потом практически не могу толком вспомнить, о чем же собственно говорили?

Я бы не беспокоился, но «женщины любят ушами». И наличие плюсов у меня в виде денег/внешности вменяемой/интересных (мне) увлечений помогает довольно мало. Т.е. иногда на ночь-две. Потом всё. Каких-то близких отношений нет.

Потому вопрос: а о чем вы говорите, кроме как о делах? В частности с женщинами.

 

cvs-255 ()

Обновился инструмент для работы с агентами в C++: SObjectizer 5.5.0

Форум — Development

SObjectizer — это реализация модели акторов для C++, позволяющая программировать на C++ с использованием работающих на разных нитях агентов, общающихся между собой посредством сообщений. SObjectizer существенно упрощает разработку событийно-ориентированных приложений, для параллельной и независимой обработки событий в которых требуется многопоточность и/или распределенность. SObjectizer использовался для создания как для мелких утилит, так и серьезных распределенных приложений, работающих под большой нагрузкой в режиме 24x7.

Последние несколько лет SObjectizer развивается на SourceForge как OpenSource проект под BSD-лицензией. Подробнее об истории, текущем состоянии и направлении движения SObjectizer можно прочитать здесь.

Версия 5.5.0 является результатом очередного, очень значимого этапа развития проекта.

Главное отличие v.5.5.0 от предыдущих версий — это отсутствие зависимости от ACE Framework. Т.е. теперь ACE в коде ядра SObjectizer не используется вообще, для SObjectizer достаточно наличия стандартной библиотеки C++11. Это означает, что SObjectizer уменьшился в размере, нужно меньше времени на сборку SObjectizer-проектов, упрощается поддержка различных компиляторов и платформ. В частности, эта версия SObjectizer тестировалась посредством MSVS2013 (Windows), GCC 4.8/4.9 (Windows, Linux), Clang 3.5.0 (Linux).

Из более мелких изменений можно отметить прямую поддержку std::chrono при работе с отложенными/периодическими сообщениями, а так же небольшое изменение названий некоторых классов/функций (с сохранением старых имен для обеспечения совместимости). Более подробная информация о нововведениях в v.5.5.0 доступна в соответствующем разделе Wiki проекта. Так же увеличилось количество страниц с описаниями базовых вещей SObjectizer.

Версия 5.5.0 может быть загружена из раздела Files или получена из Subversion-репозитория.

Примечание. Этот релиз содержит только ядро SObjectizer (т.е. проект so_5). Никакие другие подпроекты (вроде so_log или so_sysconf) в релиз не включены. Возможно, сборка SObjectizer Assembly со всеми подпроектами будет сформирована и опубликована позже (если она действительно кому-то потребуется).

PS. Анонс делается просто для того, чтобы уведомить, что такой проект есть, живет, развивается. Доступен под BSD-лицензий, т.е. даром, в том числе и для коммерческих проектов. Это не просьба сделать code review. И не попытка кому-то что-то «продать».

PPS. Специально для желающих постебаться над синтаксисом и посравнивать программирование на C++ с Perl-ом. Вот классический пример Hello, World. В традиционном, ООП-шном варианте, с созданием класса агента и переопределением виртуальных методов (хотя есть и более модерновый вариант, с использованием С++ных лямбда-функций):

#include <iostream>

// Main SObjectizer header files.
#include <so_5/all.hpp>

// Definition of an agent for SObjectizer.
class a_hello_t : public so_5::rt::agent_t
{
	public:
		a_hello_t( so_5::rt::environment_t & env )
			: so_5::rt::agent_t( env )
		{}

		// A reaction to start of work in SObjectizer.
		virtual void
		so_evt_start() override
		{
			std::cout << "Hello, world! This is SObjectizer v.5."
				<< std::endl;

			// Shutting down SObjectizer.
			so_environment().stop();
		}

		// A reaction to finish of work in SObjectizer.
		virtual void
		so_evt_finish() override
		{
			std::cout << "Bye! This was SObjectizer v.5."
				<< std::endl;
		}
};

int
main( int, char ** )
{
	try
	{
		// Starting SObjectizer.
		so_5::launch(
			// A function for SO Environment initialization.
			[]( so_5::rt::environment_t & env )
			{
				// Creating and registering single agent as a cooperation.
				env.register_agent_as_coop( "coop", new a_hello_t( env ) );
			} );
	}
	catch( const std::exception & ex )
	{
		std::cerr << "Error: " << ex.what() << std::endl;
		return 1;
	}

	return 0;
}

PPPS. Специально для желающих узнать, чем SObjectizer лучше libcppa/CAF. В двух словах — это две совершенно разные разработки, ставящие перед собой разные цели и достигающие их разными способами. Подробнее здесь и здесь.

 , , ,

eao197 ()