Byl vydán Linux Mint 22.2 s kódovým jménem Zara. Podrobnosti v přehledu novinek a poznámkách k vydání. Vypíchnout lze novou XApp aplikaci Fingwit pro autentizaci pomocí otisků prstů nebo vlastní fork knihovny libAdwaita s názvem libAdapta podporující grafická témata. Linux Mint 22.2 bude podporován do roku 2029.
Čínská společnost Tencent uvolnila svůj AI model HunyuanWorld-Voyager pro generování videí 3D světů z jednoho obrázku a určené trajektorie kamery. Licence ale nedovoluje jeho používání na území Evropské unie, Spojeného království a Jižní Koreje.
Blender Studio se spojilo s kapelou OK Go a výsledkem je videoklip k písni Impulse Purchase. Stejně jako samotný 3D software Blender je i ve videoklipu použitý animovaný chlápek open source. Kdokoli si jej může stáhnout a upravovat.
Zig Software Foundation stojící za programovacím jazykem Zig publikovala finanční zprávu za rok 2024. Současně s prosbou o finanční příspěvek.
Na čem pracují vývojáři webového prohlížeče Ladybird (GitHub)? Byl publikován přehled vývoje za srpen (YouTube). Vypíchnuta je podpora Tabulek Google, implementace Gamepad API a Cookie Store API nebo také podpora WebGL na Linuxu.
openSUSE Leap 16, včetně Leap Micra 6.2+, nově nabízí 24 měsíců podpory pro každé vydání. To je dva roky aktualizací a stability, což z něj činí nejdéle podporovanou komunitní distribuci vůbec. Leap se tak stává ideální platformou pro všechny, kdo hledají moderní, stabilní a dlouhodobě podporovanou komunitní Linux distribuci.
Národní úřad pro kybernetickou a informační bezpečnost (NÚKIB) vydal dne 3. 9. 2025 VAROVÁNÍ před hrozbou v oblasti kybernetické bezpečnosti spočívající v předávání systémových a uživatelských dat do Čínské lidové republiky a ve vzdálené správě technických aktiv vykonávané z území Čínské lidové republiky. Varováním se musí zabývat povinné osoby podle zákona o kybernetické bezpečnosti.
Americká internetová společnost Google nemusí prodat svůj prohlížeč Chrome ani operační systém Android. Rozhodl o tom soud ve Washingtonu, který tak zamítl požadavek amerického ministerstva spravedlnosti. Soud ale firmě nařídil sdílet data s jinými podniky v zájmu posílení konkurence v oblasti internetového vyhledávání. Zároveň Googlu zakázal uzavírat dohody s výrobci mobilních a dalších zařízení, které by znemožňovaly
… více »Prvního září ozbrojení policisté zatkli na na londýnském letišti Heathrow scénáristu a režiséra Grahama Linehana, známého především komediálními seriály Ajťáci, Otec Ted nebo Black Books. Během výslechu měl 57letý Graham nebezpečně zvýšený krevní tlak až na samou hranici mrtvice a proto byl z policejní stanice převezen do nemocnice. Důvodem zatčení bylo údajné podněcování násilí v jeho 'vtipných' příspěvcích na sociální síti
… více »Studentská dílna Macgyver zve na další Virtuální Bastlírnu - pravidelné online setkání všech, kdo mají blízko k bastlení, elektronice, IT, vědě a technice. Letní prázdniny jsou za námi a je čas probrat novinky, které se přes srpen nahromadily. Tentokrát jich je více než 50! Těšit se můžete mimo jiné na:
Hardware – Bus Pirate na ESP32, reverse engineering Raspberry Pi, pseudo-ZX-80 na RISC-V, PicoCalc, organizéry na nářadí z pěny nebo … více »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: