Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault with lazy implementation when switching context #179

Closed
kikofernandez opened this issue May 28, 2015 · 15 comments
Closed

Segfault with lazy implementation when switching context #179

kikofernandez opened this issue May 28, 2015 · 15 comments
Assignees

Comments

@kikofernandez
Copy link
Contributor

I got some code from @EagiZ and this crashes when using the lazy implementation. it does not when using the eager implementation.

P.S. I know it's quite a lot of code and, most likely, we can reproduce the error with a smaller snippet but this is better than nothing.

list.enc

passive class Link<t> {
  data : t
  next : Link<t>
  def init(elem : t, next : Link<t>) : void {
    this.data = elem;
    this.next = next
  }

  def getData() : t {
    this.data
  }
  def getNextLink() : Link<t>
    this.next
}

passive class List<t> {
  first : Link<t>
  last : Link<t>
  size : int

  def init() : void {
    this.first = null : Link<t>;
    this.last = null : Link<t>;
    this.size = 0;
  }

  def prepend(elem : t) : void {
    let newFirst = new Link<t>(elem, this.first) in{
      this.first = newFirst
    };

    if(this.last == null) then this.last = this.first;
    this.size = this.size + 1;
  }

  def append(elem : t) : void {
    if(this.first == null) then {
      this.prepend(elem);
    } else {
    let newLast = new Link<t>(elem, null) in {
          if(this.last != null) then this.last.next = newLast;
          this.last = newLast;
         this.size = this.size + 1;
        }
    }
  }

  def appendList(l : List<t>) : void {
    if(l.size > 0) then {
      if(this.first != null) then {
        this.last.next = l.first;
        this.last = l.last;
      } else {
        this.first = l.first;
        this.last = l.last;
      };
      this.size = this.size + l.size;
    }
  }

  def nth(n : int) : t {
    let cursor = this.first in{
      while n > 0{
        cursor = cursor.getNextLink();
        n = n - 1
      };
      cursor.getData()
    }
  }
}

quicksort.enc

import list

passive class QuickSortConfig {
  N : int -- Data size
  M : int -- max value
  seqThreshold : int

  def init() : void {
    this.N = 1000; -- If N > seqThreshold then segfault is likely to occur
    this.M = 1152921504606846976;
    this.seqThreshold = 70;
  }

  def show(dataLink : Link<int>) : void{
    if(dataLink == null) then {
      print("NULL!\n");
    } else {
    print dataLink.data;
        if dataLink.next != null then
        this.show(dataLink.next)
      else
    ()
    }
  }

  def quicksortSeq(data : List<int>) : List<int> {
    let
      dataLength = data.size
    in {
      if(dataLength < 2) then {
    data;
      } else {
      let
          pivot = data.nth(dataLength / 2)
          leftUnsorted = this.filterLessThan(data, pivot)
       leftSorted = this.quicksortSeq(leftUnsorted)

       equalElements = this.filterEqualsTo(data, pivot)

       rightUnsorted = this.filterGreaterThan(data, pivot)
       rightSorted = this.quicksortSeq(rightUnsorted)

       sortedList = new List<int>
        in {
       sortedList.appendList(leftSorted);
          sortedList.appendList(equalElements);
        sortedList.appendList(rightSorted);
       sortedList;
        }
      }
    }
  }

  def filterLessThan(data : List<int>, pivot : int) : List<int> {
    let
      result = new List<int>
      cursor = data.first
    in {
      while(cursor != null) {
    if(cursor.data < pivot) then result.append(cursor.data);
        cursor = cursor.next;
      };
      result;
    };
  }

  def filterEqualsTo(data : List<int>, pivot : int) : List<int> {
    let
      result = new List<int>
      cursor = data.first
    in {
      while(cursor != null) {
    if(cursor.data == pivot) then {
          result.append(cursor.data);
      };
        cursor = cursor.next;
      };
      result;
    };
  }

  def filterBetween(data : List<int>, leftPivot : int, rightPivot : int) : List<int> {
    let
      result = new List<int>
      cursor = data.first
    in {
      while(cursor != null) {
    if((cursor.data >= leftPivot) and (cursor.data <= rightPivot)) then result.append(cursor.data);
        cursor = cursor.next;
      };
      result;
    };
  }

  def filterGreaterThan(data : List<int>, pivot : int) : List<int> {
    let
      result = new List<int>
      cursor = data.first
    in {
      while(cursor != null) {
    if(cursor.data > pivot) then result.append(cursor.data);
        cursor = cursor.next;
      };
      result;
    };
  }

  def checkSorted(data : List<int>) : bool {
    print("Checking...\n");
    if(data.size != this.N) then {
      print("Result is not correct length!\n");
      false;
    } else {
      let
    loopVal = data.first.getData()
    temp = 0
    cursor = data.first
    breakLoop = false
      in {
    while((cursor.next != null) and not breakLoop) {
          temp = cursor.next.data;
          if(temp < loopVal) then {
            print("Result is not sorted!\n");
            breakLoop = true;
          } else {
            loopVal = temp;
            cursor = cursor.next;
          }
        };
     if(breakLoop) then false
        else true;
      }
    }
  }

  def random(a:int,b:int) : int -- At the moment, each active object does not generate random numbers independently on other objects
    embed int
      (random() % #{b}) + #{a};
    end

  def randomList() : List<int> {
    let
      l = new List<int>
      i = 0
    in {
      while(i < this.N) {
    l.prepend(this.random(0, this.M));
        i = i + 1;
      };
      print("Debug: Random list generated successfully\n");
      l;
    }
  }
}

class QuickSorter {
  relativePosition : int -- -1 = left, 0 = init, 1 = right
  config : QuickSortConfig

  def init(config : QuickSortConfig, relativePosition : int) : void {
    this.relativePosition = relativePosition;
    this.config = config;
  }

  def sort(data : List<int>) : List<int> {
    if(data.size < this.config.seqThreshold) then {
      this.config.quicksortSeq(data);
    } else {
      let
    dataLengthHalf = data.size / 2
    pivot = data.nth(dataLengthHalf)

    leftUnsorted = this.config.filterLessThan(data, pivot)
    rightUnsorted = this.config.filterGreaterThan(data, pivot)

    leftObject = new QuickSorter(this.config, -1)
    rightObject = new QuickSorter(this.config, 1)

    result = this.config.filterEqualsTo(data, pivot)
    rightResult = get rightObject.sort(rightUnsorted)
    leftResult = get leftObject.sort(leftUnsorted)
      in{
    let
          temp = leftResult
        in {
          temp.appendList(result);
          temp.appendList(rightResult);
        result = temp;
        };
        result;
      }
    }
  }
}

class Main {
  def main() : void {
    let
      config = new QuickSortConfig()
      rootActor = new QuickSorter(config, 0)
      input = config.randomList()
      result = rootActor.sort(input)
    in {
      if(config.checkSorted(get result) == true) then {
    print("List was sorted correctly!\n");
      } else {
      print("List was NOT sorted correctly!\n");
        --config.show((get result).first) -- If you want to print list
      }
    }
  }
}

@TobiasWrigstad
Copy link
Contributor

Can any more information be provided as to the nature of the crash? Does it segfault, or …?

@kikofernandez
Copy link
Contributor Author

yes, it does segfault when using lazy evaluation on mac. when using eager evaluation, it doesn't return the right result (algorithm implementation issue, not related to encore) and finishes with the expected error message, which tells you that the array is not sorted.

Debug: Random list generated successfully
Checking...
Result is not sorted!
List was NOT sorted correctly!

@TobiasWrigstad
Copy link
Contributor

Thanks!

@TobiasWrigstad TobiasWrigstad changed the title Problems with lazy implementation when switching context Segfault with lazy implementation when switching context May 28, 2015
@TobiasWrigstad
Copy link
Contributor

Is the "when switching context" confirmed?

@kikofernandez
Copy link
Contributor Author

I believe my statement was too general. It fails consistently in the clean_pool function in encore.c, when freeing a local page of the stack...

@albertnetymk
Copy link
Contributor

Minimal program to produce the bug:

passive class Node
  e : int
  next : Node

class Agent
  def getNode() : Node {
    let n = new Node in {n.e = 1; n};
  }

  def f() : Node {
    let
      a = new Agent
      n = get a.getNode()
    in {
      n.next = new Node;
      n
    }
  }

class Main
  def main() : void {
    get (new Agent).f()
  }

I don't think it's related to the future strategy used.

@albertnetymk albertnetymk self-assigned this May 28, 2015
@kikofernandez
Copy link
Contributor Author

not directly, but happens only when using the lazy strategy, since the eager doesn't need a context pool, nor calling the clean_pool function which causes the segfault

@albertnetymk
Copy link
Contributor

The issue is gone on my box. Anyone could confirm it?

@EliasC
Copy link
Contributor

EliasC commented Jun 10, 2015

@albertnetymk Your minimal example passes for me, but I'm still getting a segfault (in pop_context in encore.c:150) with the original example.

@albertnetymk
Copy link
Contributor

It seems there are two independent problems exposed by the larger code snippet. My minimal test case only captures the GC related one. The second issue is related to ucontext on mac. The PR #185 should fix it.

@albertnetymk
Copy link
Contributor

I think this could be closed now.

@EliasC
Copy link
Contributor

EliasC commented Jun 12, 2015

@EagiZ Could you try to run your program with the HEAD and confirm that you're no longer seeing these crashes (and then close this issue)?

@eastlund
Copy link
Contributor

I can't reproduce the crashes anymore on Linux, seems to be fixed. (@kikofernandez is the author of this issue tho)

@TobiasWrigstad
Copy link
Contributor

Is this still open? Can someone try to confirm? If we cannot reproduce (90 days later) we should close this.

@kikofernandez
Copy link
Contributor Author

I cannot reproduce it. closing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants