VST 3 je nově pod licencí MIT. S verzí 3.8.0 proběhlo přelicencování zdrojových kódů z licencí "Proprietary Steinberg VST3 License" a "General Public License (GPL) Version 3". VST (Virtual Studio Technology, Wikipedie) je softwarové rozhraní pro komunikaci mezi hostitelským programem a zásuvnými moduly (pluginy), kde tyto moduly slouží ke generování a úpravě digitálního audio signálu.
Open source 3D herní a simulační engine Open 3D Engine (O3DE) byl vydán v nové verzi 25.10. Podrobný přehled novinek v poznámkách k vydání.
V Londýně probíhá dvoudenní Ubuntu Summit 25.10. Na programu je řada zajímavých přednášek. Zhlédnout je lze také na YouTube (23. 10. a 24. 10.).
Gemini CLI umožňuje používání AI Gemini přímo v terminálu. Vydána byla verze 0.10.0.
Konference OpenAlt 2025 proběhne již příští víkend 1. a 2. listopadu v Brně. Nabídne přibližně 80 přednášek a workshopů rozdělených do 7 tematických tracků. Program se může ještě mírně měnit až do samotné konference, a to s ohledem na opožděné úpravy abstraktů i případné podzimní virózy. Díky partnerům je vstup na konferenci zdarma. Registrace není nutná. Vyplnění formuláře však pomůže s lepším plánováním dalších ročníků konference.
Samsung představil headset Galaxy XR se 4K Micro-OLED displeji, procesorem Snapdragon XR2+ Gen 2, 16 GB RAM, 256 GB úložištěm, operačním systémem Android XR a Gemini AI.
Před konferencí Next.js Conf 2025 bylo oznámeno vydání nové verze 16 open source frameworku Next.js (Wikipedie) pro psaní webových aplikací v Reactu. Přehled novinek v příspěvku na blogu.
Sovereign Tech Fund oznámil finanční podporu následujících open source projektů: Scala, SDCC, Let's Encrypt, Servo, chatmail, Drupal, Fedify, openprinting, PHP, Apache Arrow, OpenSSL, R Project, Open Web Docs, conda, systemd a phpseclib.
Bylo vydáno OpenBSD 7.8. S předběžnou podporou Raspberry Pi 5. Opět bez písničky.
Valkey (Wikipedie) byl vydán v nové major verzi 9.0. Valkey je fork Redisu.
bool Shell::popen3(const string& command, pid_t* pid, Pipes3 pipes)
{
if (!pid) return false;
pid_t cpid;
int p_stdin[2], p_stdout[2], p_stderr[2];
if (pipe(p_stdin) || pipe(p_stdout) || pipe(p_stderr)) goto cleanup;
cpid = fork();
if (cpid < 0) goto cleanup;
if (cpid == 0)
{
//child process
close(p_stdin[P_WRITE]);
dup2(p_stdin[P_READ], STDIN_FILENO);
close(p_stdout[P_READ]);
dup2(p_stdout[P_WRITE], STDOUT_FILENO);
close(p_stderr[P_READ]);
dup2(p_stderr[P_WRITE], STDERR_FILENO);
execl("/bin/sh", "sh", "-c", command.c_str(), NULL);
exit(-1);
}
*pid = cpid;
pipes[P_IN] = fdopen(p_stdin[P_WRITE], "w");
pipes[P_OUT] = fdopen(p_stdout[P_READ], "r");
pipes[P_ERR] = fdopen(p_stderr[P_READ], "r");
return true;
cleanup:
close(p_stdin[P_READ]); close(p_stdin[P_WRITE]);
close(p_stdout[P_READ]); close(p_stdout[P_WRITE]);
close(p_stderr[P_READ]); close(p_stderr[P_WRITE]);
return false;
}
Celá funkce pracuje celkom dobře, akorát je problém s ukončením child processu.Řešení dotazu:
Po zavolání téhle funkce čtu stdin/stderr výstup child programu a nějak ho zpracovávám.
Můj (rodičovský) proces se tak zasekne na volání fgets/fgetc apod.Tohle čtete jak? Správně to musíte číst oboje najednou, tj. přes select() ... ideálně, pokud budete chtít i zapisovat, tak musíte selectovat všechny 3 roury, jinak může dojít k deadlocku mezi libovolnýma dvěma: např. Vy čekáte na výstup potomka a ten čeká na vstup od Vás, nebo potomek chce zapisovat do stderr, ale ten blokuje, protože má plný buffer, protože nečtete rouru stderr, protože jste zablokován čtením roury stdout. Všechny tyto problémy řeší zmíněný select(). Ad ukončení procesu potomka: Pokud potomek skončí (i neočekávaně), dostanete při čtení EOF (pokud se opravdu pokoušíte číst a nejste v deadlocku, viz výše) a při zápisu EPIPE (a signál SIGPIPE, který standardně Váš proces zabije, takže je vhodné to mít ošetřené). Ad zombie: Když potomek skončí, přejde do stavu zombie automaticky a zůstane v něm dokud si nevyzvednete jeho exit status pomocí nějakého volání z rodiny wait(). Při skončení potomka dostanete taky signál SIGCHLD, abyste věděl, že si máte status vyzvednout, záleží pak na logice Vaší aplikace, jestli to udělá hned, nebo v rámci např. čtecího cyklu. Management procesů je obecně netriviální záležitost. To ještě neřešíte např. ukončení potomků potomka (/bin/sh pouští další procesy), případně korektní ukončení (zabití) potomků, pokud se Vaše aplikace rozhodne skončit/spadne...
select() a zkusil implementovat, ale chová se to teď nějak úplně divně.
timeout.tv_sec = 5;
timeout.tv_usec = 0;
bool go_on = true;
while (go_on)
{
FD_ZERO(&set_r);
FD_SET(fileno(pipes[P_OUT]), &set_r);
nfds = max(nfds, fileno(pipes[P_OUT]));
FD_SET(fileno(pipes[P_ERR]), &set_r);
nfds = max(nfds, fileno(pipes[P_ERR]));
timeout.tv_sec = 1;
timeout.tv_usec = 0;
cout << "select: " << (success = select(nfds, &set_r, NULL, NULL, &timeout)) << "\n";
if (success == -1) return false;
go_on = false;
while (FD_ISSET(fileno(pipes[P_OUT]), &set_r))
{
fgets(buffer_r, BUF_LEN, pipes[P_OUT]);
out << "[stdout] " << buffer_r;
go_on = true;
}
if (FD_ISSET(fileno(pipes[P_ERR]), &set_r))
{
fgets(buffer_r, BUF_LEN, pipes[P_ERR]);
out << "[stderr] " << buffer_r << "\n";
go_on = true;
}
}
Tento kód vypíše pouze první řádku výstupu child procesu, potom už select() jen nulu,
ačkoli když přesto čtu stdin, jsou tam znaky k přečtení.
(Stdin zatím neuvažuju, dokud nerozchodím alespoň stdout a stderr.)
)

Srovnejte si select(2) a pselect(2), pokud chcete řešit souběh s nastavováním obsluh signálů.
Mimochodem timeout můžete nechat na nekončnu, protože příchodem signálu bude volání přerušeno a select() vrátí -1 a errno bude EINTR.
Já signály vůbec nezpracovávám
se už žádný signál neodešle
Tak jde o signály, nebo ne?
Když chcípne potomek, tak čtecí konec roury vrací EOF, na což samozřejmě select() zareaguje tím, že v množině čtecích deskriptorů se objeví připravený deskriptor, ze kterého read() vrátí 0.
Select při čtení z ukončeného procesu označí fd jako že z něj de číst, ale při čtení dostanete přečteno 0 bajtů = EOF.Mně se select() po skončení child procesu zasekne, pokud *timeout == NULL. Mám ověřené, že to je právě volání select(), na kterém se to zarazí.
Signál CHLD Vám přijde pokud ho neignorujete (nastavíte si handler).Je nějaký zásadní důvod, proč bych to měl dělat? Polling afaik ničemu nevadí. CPU nevytěžuje.
Mně se select() po skončení child procesu zasekne, pokud *timeout == NULL. Mám ověřené, že to je právě volání select(), na kterém se to zarazí.To je asi tím že neselectujete chybové stavy (třetí fdset).
Je nějaký zásadní důvod, proč bych to měl dělat? Polling afaik ničemu nevadí. CPU nevytěžuje.Maskujete si tím chybové chování.
To je asi tím že neselectujete chybové stavy (třetí fdset).Zkusil jsem do
exceptfds dát stind a stdout pajpy, ale select() se při *timeout = NULL stále zasekává.exceptfds jinak? Z man select to není úplně zřejmý...Maskujete si tím chybové chování.Sledovat, jestli
select() nevrací -1 nestačí?
exceptfds taky sleduju pro případný errory... no tak snad už to je plně košér
takže selectem neodlišim stav, kdy child potřebuje něco čístJelikož jsou mezitím různé buffery a potenciálně nemusí být příjemce ani na stejném stroji, tak to opravdu nepoznáte. Ale nedovedu si představit situaci kde byste něco takového využil. Normální duplexní protokoly fungují na principu požadavek a odpověď.
exceptfds taky sleduju pro případný errory... no tak snad už to je plně košérKdyž tak pro jistotu ještě ukažte jednou ten kód. Nezdá se mi, že by měl druhý fdset nějaký vliv na funkci prvního a třetího.
Když tak pro jistotu ještě ukažte jednou ten kód. Nezdá se mi, že by měl druhý fdset nějaký vliv na funkci prvního a třetího.Ok, ale upozorňuju, že ten kód je stále dost neučesanej, možná tam jsou proměnný navíc, instream(stdin) vyhodim, musim dodělat error handling při otevřených pajpách, ...atd.
bool Shell::issue(const string& command, ostream& out, istream& in, int* retvalue, bool* normal_exit)
{
if (!retvalue) return false; //ep_nodep
if (!normal_exit) return false;
if (command.empty()) return false;
Pipes3 pipes;
pid_t pid, w;
fd_set set_r, set_w, set_err;
int nfds = 0;
struct timeval timeout;
int success;
char buffer_r[BUF_LEN];
string buffer_w;
int bytes;
int child_status;
string prefix = command.substr(0, command.find_first_of(' '));
stringstream ss;
if (!popen3(command, &pid, pipes)) return false;
// interrogate child process output/(input)
bool go_on = true;
while (go_on)
{
FD_ZERO(&set_r);
FD_SET(pipes[P_OUT], &set_r);
nfds = max(nfds, pipes[P_OUT]);
FD_SET(pipes[P_ERR], &set_r);
nfds = max(nfds, pipes[P_ERR]);
FD_ZERO(&set_w);
FD_SET(pipes[P_IN], &set_w);
nfds = max(nfds, pipes[P_IN]);
FD_ZERO(&set_err);
FD_SET(pipes[P_OUT], &set_err);
FD_SET(pipes[P_ERR], &set_err);
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
if(select(nfds+1, &set_r, &set_w, &set_err, /*&timeout*/NULL) == -1 ) /* TODO: error */;
if (FD_ISSET(pipes[P_OUT], &set_err)) /*error*/;
if (FD_ISSET(pipes[P_ERR], &set_err)) /*error*/;
//if (FD_ISSET(pipes[P_IN], &set_w)) /*always*/;
if (FD_ISSET(pipes[P_OUT], &set_r))
{
bytes = read(pipes[P_OUT], buffer_r, BUF_LEN);
buffer_r[bytes] = '\0';
ss << buffer_r;
while (ss.good())
{
ss.getline(buffer_r, BUF_LEN);
if ((ss.gcount() > 0) && (strlen(buffer_r) > 0)) out << " [" << prefix << "] " << buffer_r << "\n";
}
ss.clear(); /* TODO: jeste nejak vyprazdnit stringstream*/
}
if (FD_ISSET(pipes[P_ERR], &set_r))
{
bytes = read(pipes[P_ERR], buffer_r, BUF_LEN);
buffer_r[bytes] = '\0';
ss << buffer_r;
while (ss.good())
{
ss.getline(buffer_r, BUF_LEN);
if ((ss.gcount() > 0) && (strlen(buffer_r) > 0)) out << " [" << prefix << "] " << buffer_r << "\n";
}
ss.clear();
}
/*if (FD_ISSET(fileno(pipes[P_IN]), &set_w))
{
/// TODO: oddelat stdin
}*/
w = waitpid(pid, &child_status, WNOHANG|WUNTRACED|WCONTINUED);
if (w == -1)
{
//TODO: error handling
go_on = false;
} else if (w != 0)
{
if (WIFEXITED(child_status))
{
*retvalue = WEXITSTATUS(child_status);
*normal_exit = true;
go_on = false;
} else if (WIFSIGNALED(child_status))
{
*retvalue = WTERMSIG(child_status);
*normal_exit = false;
go_on = false;
}
}
}
pclose3(pipes);
return true;
}
Nejspíš budu taky moct přehodit celou waitpid část až za smyčku, páč timeout může nyní být nekonečný.
/*error*/, protože ignorování chyby může být zdroj potíží úplně jinde. Když jsme u toho, vidím, že se snažíte o C++, tak co třeba zkusit občas něco thrownout?
Nejspíš budu taky moct přehodit celou waitpid část až za smyčku, páč timeout může nyní být nekonečný.Z principu věci by to mělo být až za smyčkou, protože smyčka by měla skončit až skončí proces (nebo při chybě). Podobně tak je možno naplnit všechny fdsety coby vzor před smyčkou a uvnitř smyčky inicializovat pracovní fdsety pomocí memcpy (select je zmodifikuje, takže inicializaci se nevyhnete, jen je to takto rychlejší). Poslední věc co by asi stála za zvážení je odsunout něco do separátních podprogramů, na mě je tam už moc lokálních proměnných.
Na error kontrolujte i P_IN.Ok, na to jsem zapomněl...
Když jsme u toho, vidím, že se snažíte o C++, tak co třeba zkusit občas něco thrownout?Hm, to bych případně mohl taky. Na jiných místech programu exceptions používám, takže proč ne... ještě ten error handling nějak vymyslim a zvážím to.
Podobně tak je možno naplnit všechny fdsety coby vzor před smyčkou a uvnitř smyčky inicializovat pracovní fdsety pomocí memcpy (select je zmodifikuje, takže inicializaci se nevyhnete, jen je to takto rychlejší).Jj, měl jsem tam dřív něco jako tmp_set_r a další, ale oddělal jsem je, protože jsem při hledání chyb podezříval kde co. Zas to dám zpátky.
Poslední věc co by asi stála za zvážení je odsunout něco do separátních podprogramů, na mě je tam už moc lokálních proměnných.Tjn, je toho tam trochu moc, taky už mi to vadí. Nějak to časem pořešim.
Popravdě řečeno by se mi asi nejvíc líbilo řešení, kdy funkce by vracely nějakou malou "úspěchovou" třídu,Smysl výjimek je v tom, že nemusíte vracet nic (a obvykle to co říkáte je pokryto více typy výjimek). Kód pak není přecpán if-y a navíc se obrací logika ignorace chyby - pokud s ní nic neuděláte tak program skončí, verzus pokud ignorujete návratovou hodnotu, tak se nestane nic.
Mít tak víc volnýho času, věčný to problém...Ten mám taky. Proto se snažím dokumentovat a psát pořádně hned od prvního řádku, abych pak po půl roce neměl chuť se za ten bordel nakopat do zadku.
Chtěl jsem tim říct, že obcházíte něco, co "nefunguje" jak by mělo.Maskujete si tím chybové chování.Sledovat, jestli select() nevrací -1 nestačí?
Tiskni
Sdílej: