Byla vydána nová major verze 7.0 živé linuxové distribuce Tails (The Amnesic Incognito Live System), jež klade důraz na ochranu soukromí uživatelů a anonymitu. Nově je postavena je na Debianu 13 (Trixie) a GNOME 48 (Bengaluru). Další novinky v příslušném seznamu.
Společnost Meta na dvoudenní konferenci Meta Connect 2025 představuje své novinky. První den byly představeny nové AI brýle: Ray-Ban Meta (Gen 2), sportovní Oakley Meta Vanguard a především Meta Ray-Ban Display s integrovaným displejem a EMG náramkem pro ovládání.
Po půl roce vývoje od vydání verze 48 bylo vydáno GNOME 49 s kódovým názvem Brescia (Mastodon). S přehrávačem videí Showtime místo Totemu a prohlížečem dokumentů Papers místo Evince. Podrobný přehled novinek i s náhledy v poznámkách k vydání a v novinkách pro vývojáře.
Open source softwarový stack ROCm (Wikipedie) pro vývoj AI a HPC na GPU od AMD byl vydán ve verzi 7.0.0. Přidána byla podpora AMD Instinct MI355X a MI350X.
Byla vydána nová verze 258 správce systému a služeb systemd (GitHub).
Byla vydána Java 25 / JDK 25. Nových vlastností (JEP - JDK Enhancement Proposal) je 18. Jedná se o LTS verzi.
Věra Pohlová před 26 lety: „Tyhle aféry každého jenom otravují. Já bych všechny ty internety a počítače zakázala“. Jde o odpověď na anketní otázku deníku Metro vydaného 17. září 1999 na téma zneužití údajů o sporožirových účtech klientů České spořitelny.
Byla publikována Výroční zpráva Blender Foundation za rok 2024 (pdf).
Byl vydán Mozilla Firefox 143.0. Přehled novinek v poznámkách k vydání a poznámkách k vydání pro vývojáře. Nově se Firefox při ukončování anonymního režimu zeptá, zda chcete smazat stažené soubory. Dialog pro povolení přístupu ke kameře zobrazuje náhled. Obzvláště užitečné při přepínání mezi více kamerami. Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 143 bude brzy k dispozici také na Flathubu a Snapcraftu.
Byla vydána betaverze Fedora Linuxu 43 (ChangeSet), tj. poslední zastávka před vydáním finální verze, která je naplánována na úterý 21. října.
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 throw
nout?
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: