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

Endless loop in Verilog::Preproc #913

Closed
veripoolbot opened this issue Apr 28, 2015 · 7 comments
Closed

Endless loop in Verilog::Preproc #913

veripoolbot opened this issue Apr 28, 2015 · 7 comments
Assignees

Comments

@veripoolbot
Copy link
Collaborator


Author Name: Stefan Tauner (@stefanct)
Original Redmine Issue: 913 from https://www.veripool.org
Original Date: 2015-04-28
Original Assignee: Wilson Snyder (@wsnyder)


I think I have found a bug in the netlist parser but since I have never debugged XS code yet, I am a bit stuck.
Both, the version shipped with Ubuntu 14.04 (3.403) as well as the current git HEAD are affected.

The last thing done within perl is @$self->_open($filename);@ in line 110 of Preproc.pm originating in my code from @$a_netlist->read_file(filename=>$filename)@.
After that there is an infinite loop in the XS code.
I have not looked at it yet (have to run in a few) and will investigate later if need be.

The last thing I see in strace is this:

open("test.vqm", O_RDONLY)              = 5
read(5, "//\n// Written by Synplify\n// Pro"..., 65536) = 65536
read(5, "VCC),\n\t.ena(VCC),\n\t.asdata(prer_"..., 65536) = 63118
brk(0x3821000)                          = 0x3821000
read(5, "", 65536)                      = 0
read(5, "", 65536)                      = 0
...

I am executing the @read_file@ call from a Perl::Tk application if a button is pressed.
Of course the GUI gets stuck while working on the netlist but in my current implementation that's just fine... if it would return at some time. ;)

Now the most fascinating part... the same code works in a standalone application (without Tk) just fine.
This is what strace prints in the respective part there:

...
open("test.vqm", O_RDONLY)              = 4
read(4, "//\n// Written by Synplify\n// Pro"..., 65536) = 65536
brk(0x29ba000)                          = 0x29ba000
read(4, "VCC),\n\t.ena(VCC),\n\t.asdata(prer_"..., 65536) = 63118
read(4, "", 65536)                      = 0
close(4)                                = 0
...

So the only apparent difference is the changed file descriptor.
But I don't think that it really matters because the read data is obviously the same and correct.

Any advice is very welcomed, thanks!

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Stefan Tauner (@stefanct)
Original Date: 2015-04-28T15:27:14Z


The problem is that @errno@ is never reset in @VPreProcImp::readWholefile()@.
In my application - for whatever reason - @errno@ is already set to @EAGAIN@ before the @while(!eof)@ loop, so the current implementation obviously will loop forever:

     while (!eof) {
         todo = INFILTER_IPC_BUFSIZ;
         got = read (fd, buf, todo);
         if (got>0) {
             outl.push_back(string(buf, got));
         }
         else if (errno == EINTR || errno == EAGAIN
#ifdef EWOULDBLOCK
	     || errno == EWOULDBLOCK
#endif
             ) {
         } else { eof = true; break; }
     }

Resetting @errno@ anywhere in the loop will fix my problem and potentially others. I have added @errno = 0;@ to the empty @else if@ branch and that works fine, apart from pointlessly reading 0 bytes after the end of file. Normally I would suggest to use a counter to accumulate the total number of bytes read and compare that to the file size... but since you apparently support piping in gzipped file via popen this will of course not work. Cheers!

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-04-28T16:47:09Z


Can you check that setting errno = 0 just before the read() call solves your problem?

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Stefan Tauner (@stefanct)
Original Date: 2015-04-28T19:39:40Z


It does. However, doing it outside the loop keeps the whole construct erroneous. Think about the following scenario:

  1. A legal @READ()@ gets interrupted by an external signal (and hence sets @errno=EINTR@).
  2. The loop continues until the end of the file and thus @READ()@ begins to return 0 at each call
  3. Because @errno@ is never cleared the loop will never end, just like in my case but for a different reason

So I strongly discourage from just resetting it before the loop. It will fix the bug I experienced but will not make the loop correct.

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-04-28T19:43:49Z


Sorry, I said just before the read, not before the loop. This.

     while (!eof) {
         todo = INFILTER_IPC_BUFSIZ;
         errno = 0;  //<<<<<<<<<<<<<<<<<<<<
         got = read (fd, buf, todo);
         if (got>0) {
             outl.push_back(string(buf, got));
         }
         else if (errno == EINTR || errno == EAGAIN
#ifdef EWOULDBLOCK
          || errno == EWOULDBLOCK
#endif
             ) {
         } else { eof = true; break; }
     }

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Stefan Tauner (@stefanct)
Original Date: 2015-04-28T19:46:44Z


Right, sorry! This fixes it of course (too), thanks.

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-04-28T19:52:09Z


Fixed in git towards 3.413. Thanks much for diagnosing this so well.

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2015-06-26T10:30:32Z


In 3.414.

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

2 participants