Commit b854d122 authored by Kevin Wolf's avatar Kevin Wolf

kernel2: Zusammengesetzte Streams gefixt

! kernel2: Beim Aufräumen von Ressourcen muss man aufpassen, dass man
  nicht Ressourcen wegräumt, die noch von einem zusammengesetzten Stream
  benutzt werden.

  Um das zu fixen, gestaltet dieser Commit die Funktionsweise von Pipes
  grundsätzlich um: Statt in einem Stream für Lesen und Schreiben auf
  zwei verschiedene Ressourcen zu verweisen und zwei Dateizeiger zu
  verwalten, sind das jetzt zwei unabhängige Streams, die mittels
  lio_composite_stream() zusammengesetzt werden.

  Gleichzeitig hat ein lio_stream* jetzt entweder s->is_composite und
  verweist auf zwei andere Streams (statt vorher Ressourcen), die jetzt
  auch gerefcountet werden, oder er ist ein normaler Stream und verweist
  auf eine Ressource und hat einen Dateizeiger. Alle Funktionen, die auf
  die Ressource zu einem Stream zugreifen wollen, müssen jetzt für
  zusammengesetzte Streams erst einmal bis zum Wurzelstream durchgehen.

  Das fixt Rot beim Schließen der letzten Instanz des zusammengesetzten
  stderr, das getterm produziert.

* kernel2: lio_composite_stream() akzeptiert jetzt auch NULL für die
  beiden Parameter. In diesem Fall fehlt dem Ergebnisstream einfach die
  Les- bzw. Schreibbarkeit.
Signed-off-by: Kevin Wolf's avatarKevin Wolf <kevin@tyndur.org>
parent 938e1c34
......@@ -45,16 +45,26 @@ struct lio_resource;
struct lio_tree;
struct lio_stream {
struct lio_resource* res;
union {
struct {
struct lio_resource* res;
uint64_t pos;
struct lio_resource* res_read;
uint64_t pos_read;
struct lio_resource* res_write;
uint64_t pos_write;
} simple;
struct {
struct lio_stream* read;
struct lio_stream* write;
} composite;
};
bool is_composite;
int flags;
bool eof;
/* Der Userspace-Handle wird in usp_refcount separat verwaltet; wenn ein
* Stream mehrfach an den Userspace herausgegeben wird, wird ref trotzdem
* nur einmal erhöht. */
int ref;
int usp_refcount;
};
......
This diff is collapsed.
......@@ -131,13 +131,17 @@ void lio_destroy_pipe(struct lio_resource* res)
void pipe_close(struct lio_stream* s)
{
s->res_write->moredata = false;
BUG_ON(s->is_composite);
if (s->res_read->ref == 0) {
lio_destroy_pipe(s->res_read);
}
if (s->res_write->ref == 0) {
lio_destroy_pipe(s->res_write);
/* Eigentlich müssen wir moredata = false nur setzen, wenn der schreibende
* Stream geschlossen wird. Wir wissen an dieser Stelle aber nicht mehr, ob
* das der lesende oder der schreibende Stream war. Das macht deswegen
* nichts, weil moredata niemanden mehr interessiert, wenn der lesende
* Stream geschlossen ist. */
s->simple.res->moredata = false;
if (s->simple.res->ref == 0) {
lio_destroy_pipe(s->simple.res);
}
}
......
......@@ -577,9 +577,12 @@ static int load_children(struct lio_resource* res)
static void close(struct lio_stream* stream)
{
struct lio_resource* res = stream->res;
struct lio_resource* res;
struct lio_op_close* oc;
BUG_ON(stream->is_composite);
res = stream->simple.res;
oc = (struct lio_op_close*) alloc_op(res, sizeof(*oc));
if (oc == NULL) {
return;
......
......@@ -753,6 +753,9 @@ static void test11(void)
test_assert(rbuf[len - 1] == '\0');
test_assert(!strcmp(rbuf, "Signifant"));
ret = lio_read(rd, 32, rbuf);
test_assert(ret == 0);
lio_close(rd);
/* Bidirektionale Pipe */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment