/tmp directory problem in cygwin

6 views
Skip to first unread message

Roger Kaufman

unread,
May 28, 2023, 9:56:36 PM5/28/23
to anti...@googlegroups.com
Hi Adrian,

I'm working on some python files and I came up a way to take off file
input as would be done from a C++ program e.g.

off_util cube | script
script cube.off
script cube

Here is code sample from one script.

def open_off_file(tmp_dir, model, work_file):
    # read from file argument or stdin. write a copy of off file in
temporary directory
    off_file = tmp_dir.name + "/off_file.off"

    # try using the input file name or built in model name
    if (model != ""):
      ret = os.system("off_util %s > %s 2>/dev/null" % (model, off_file))

    # if no file name was given or off_util failed try reading from
standard input
    # will hang if nothing at standard input
    if (model == "" or ret != 0):
      fout = open(off_file, "w")
      fout.writelines(sys.stdin.readlines())
      fout.close()

    # rename off_file.off to expected name
    ret = os.system("mv %s %s/%s" % (off_file, tmp_dir.name, work_file))

... then

# create temporary directory for input file
tmp_dir = tempfile.TemporaryDirectory()

open_off_file(tmp_dir, args.off_file, "tmp_base.off")

# change to temporary directory and work inside of it
os.chdir(tmp_dir.name)


I don't mind working this way and I wouldn't change it now as it ends up
being easier, but originally I had tried to make temporary files.

On Cygwin Antiprism programs won't input or output anything in /tmp when
outside of /tmp.

A simple example is

off_util cube -o /tmp/cube.off (fails)
off_util cube > /tmp/cube.off (succeeds)
antiview /tmp/cube.off (fails)

but...

cd /tmp
off_util cube > cube.off (succeeds)
antiview cube.off (succeeds)

The umask which I have never changed is 022 (on ubuntu it is 007 maybe I
should tighten it). Changing the umask to permissive 000 didn't help.
Permission didn't matter.

I haven't found anything on this. Normal commands like cat /tmp/cube.off
work so it might be something weird about compiling in Cygwin. Maybe it
is time to cross compile in Ubuntu.

Note: I don't care if we don't find a fix to this as the above code
works ok.

Some further research... I put this code in util.cc
FILE *fopen_file(string &fpath)
{
  backslash_to_forward(fpath);
  system("ls -l /tmp/cube.off");
  fprintf(stderr, "file = '%s'\n", fpath.c_str());
  FILE *file = fopen(fpath.c_str(), "r");
  if (file == NULL) {
    fprintf(stderr, "fopen failed, errno = %d\n", errno);
  }
  if (file) {
    struct stat st;
    fstat(fileno(file), &st);
    if (S_ISDIR(st.st_mode)) {
      fclose(file);
      file = nullptr;
    }
  }
  return file;
}

The result of opening the file is here. Note that the first line is the
result of ls -l /tmp/cube.off so it exists. Something deeper is going on.

./antiview /tmp/cube.off
-rw------- 1 Roger Roger 571 May 28 21:05 /tmp/cube.off
file = '/tmp/cube.off'
fopen failed, errno = 2
-rw------- 1 Roger Roger 571 May 28 21:05 /tmp/cube.off
file = 'alt_names.txt'
fopen failed, errno = 2
-rw------- 1 Roger Roger 571 May 28 21:05 /tmp/cube.off
file = '/cygwin64/home/Roger/antiprism_rk/share/models/alt_names.txt'
-rw------- 1 Roger Roger 571 May 28 21:05 /tmp/cube.off
file = '/usr/local/share/antiprism/models/alt_names.txt'
fopen failed, errno = 2
antiview: error: could not open input file '/tmp/cube.off': not found
(or invalid)

Roger

Adrian Rossiter

unread,
May 29, 2023, 2:33:54 AM5/29/23
to anti...@googlegroups.com
Hi Roger

On Sun, 28 May 2023, Roger Kaufman wrote:
> On Cygwin Antiprism programs won't input or output anything in /tmp when
> outside of /tmp.
...
> off_util cube -o /tmp/cube.off (fails)
> off_util cube > /tmp/cube.off (succeeds)

The important difference between these might be that off_util is opening
the file in the first command, and the shell is opening it in the second,
and so maybe the shell is doing some magic on paths that start /tmp that
isn't available to off_util.

On the other hand, when you change directory to /tmp the paths are
relative and and there is agreement on the working directory, and hence
the location of the file.

Could this be relevent?

https://cygwin.com/cygwin-ug-net/using.html#usertemp

It seems unlikely, but do the shell and the program have different
temporary directories for some reason?

Adrian.
--
Adrian Rossiter
adr...@antiprism.com
http://antiprism.com/adrian

Roger Kaufman

unread,
May 29, 2023, 10:56:31 PM5/29/23
to anti...@googlegroups.com
Hi Adrian,

On 5/29/2023 2:33 AM, Adrian Rossiter wrote:
> Could this be relevent?
>
> https://cygwin.com/cygwin-ug-net/using.html#usertemp
>
> It seems unlikely, but do the shell and the program have different
> temporary directories for some reason?

No but that is interesting. When I put it in Cygwin started using the
Windows temp directory. But it didn't fix the problem.

In fact the problem is worse than I thought. Any time there is
involvement of the path above home it fails.

off_util cube.off | antiview (succeeds)
off_util /home/roger/cube.off | antiview (fails)

I don't normally use full paths but in the script that I'm working on
the problem with, I needed to do
os.path.abspath() so that it would work on files outside the current
directory.

But I finally hit on how to get around it.

(from home directory in cygwin)
off_util /tmp/cube.off (fails)
off_util ../../tmp/cube.off (succeeds!)

So instead the script uses relpath() and it works in all cases now.

args.off_file = os.path.relpath(args.off_file, '~/..')

It also works in Ubuntu bash.

So it no longer strictly needs the temporary working directory, however,
in the case of the script it is convenient cleanup so it is one way to
do it. The read_off_file() function could just as easily take the
current directory as its working directory and then don't clean up if
the working files are desired leftovers.

I attached the script. It is the one I used to make "kaufman polyhedra"
but I added an option to use Conway join as a comparison. I have sent
canonical output to /dev/null but if it takes a while you can't see the
progression. Maybe I should just let it be noisy.

kaufman cube.off 5 | antiview
kaufman cube.off 5 -c | antiview
kaufman cube 5 | antiview
off_util cube | kaufman 5 | antiview

Roger
kaufman.zip

Roger Kaufman

unread,
May 30, 2023, 4:47:09 PM5/30/23
to anti...@googlegroups.com
Hi Adrian,

On 5/29/2023 10:56 PM, Roger Kaufman wrote:
> I attached the script. It is the one I used to make "kaufman
> polyhedra" but I added an option to use Conway join as a comparison. I
> have sent canonical output to /dev/null but if it takes a while you
> can't see the progression. Maybe I should just let it be noisy.

I put a verbosity option in the script as it does sometimes take time to
run canonical.

One thing I realized is the last the last convex hull produced by the
script isn't run through canonical.


Looking closer I found that canonical runs on a perfectly canonical
model and can actually degrade it.

conway R100 | canonical -l 15 | canonical | antiview

I put in a precheck to see if the model will pass as canonical at the
input -l. If it is, it cancels the canonicalization but it still outputs
the report at the end. I think this makes sense; if its already
canonical the job is not needed.

As a test, if a cube is made the size to have the right volume it will
pass as canonical going in.

off_trans -S 'sqrt(2)' cube | canonical | antiview

As another test, it won't do the second canonical because it passes at
that -l setting and can't be improved.

conway dR20 | canonical -l 12 | canonical -l 10 | antiview

The final report had tested edge intersections at a fixed epsilon of
1e-11. I think I misunderstood a conversion

https://groups.google.com/g/antiprism/c/QeTlFKdkkho/m/2cY8DiflCgAJ

The problem had been that at an input -l it would never pass the edge
intersection test so I set a fixed threshold. But if -l is raised the
test stays at 1e-11 which doesn't reflect what they are improving on.

I made 1e-11 the most it can be but when they set -l higher it is 'user
epsilon * 100'. Testing show that if with * 10, the test would most
often not pass. e.g if -l is 14, the testing epsilon with be 1e-12. The
testing epsilon is output to the screen as has always been.

Roger

Roger Kaufman

unread,
May 31, 2023, 1:11:43 PM5/31/23
to anti...@googlegroups.com
Hi Adrian,

On 5/30/2023 4:46 PM, Roger Kaufman wrote:
> I put in a precheck to see if the model will pass as canonical at the
> input -l. If it is, it cancels the canonicalization but it still
> outputs the report at the end. I think this makes sense; if its
> already canonical the job is not needed.

I added the convexity check to the precheck for  scoring if the input
model is canonical at the input -l.

This should be the last that needs done with the program if you are
waiting to do a build.


A good test of this can be done by doing j^2C in conway. For some
reason, even at -l 15 this model still has creases in some faces.

conway j^2C | canonical -l 15 | conv_hull | antiview

But without checking for creases in the precheck a later run of
canonical -l 16 was bypassing the algorithm because the edges all
intersect. -l 16 will make the model without creases and doesn't thrash
on my machine.

conway j^2C | canonical -l 16 | conv_hull | antiview


I've been wondering whats going on with math error in a canonical model.
George Hart says on
https://www.georgehart.com/virtual-polyhedra/canonical.html

1. all the edges are tangent to the unit sphere,
2. the origin is the center of gravity of the points at which the edges
touch the sphere,
3. the faces are flat (i.e. the vertices of each face lie in some
plane), but are not necessarily regular.

I'm not sure how all the algorithms finish, but in the mathematica
algoritm, its when the vertices stop being moved within a limit.

My thinking is, if there is still some error it will be multiplied in
the edge intersections so if they don't all intersect they can be
improved by raising -l.
Then, even if all the edges intersect, any error left over will be
multiplied by the number of edges in a face. Planarity can be improved
by raising -l some more.

That is why some models can be canonicalized even up to -l 16 and still
have creases in the faces of a convex hull. This model has creases at -l
15 but will thrash (on my machine) at -l 16.

conway eabaC -f s | canonical -l 15 | antiview -v 0.01

Getting point 3 (planarity) is the most computational intensive part of
canonical models and for some models its out of reach for 64 bit processing.

Roger

Roger Kaufman

unread,
Jun 1, 2023, 1:13:25 AM6/1/23
to anti...@googlegroups.com
Hi Adrian,

On 5/31/2023 1:11 PM, Roger Kaufman wrote:
> This should be the last that needs done with the program if you are
> waiting to do a build.

I found a bug in canonical when the shuffle indexes feature was used. It
caused an error in the canonical algorithm but it was the fault of
shuffle indexes.

conway j^3C -f s | canonical -s a -c c | antiview

The elements were being replaced using raw_ facilities for example
'geom.raw_verts() = shuffled_verts;' and this seemed to cause some
memory problems. Instead they are now cleared and then used the add
functions.

I also added some of George Harts description of what a canonical
polyhedra is to the extended help.

Roger

Adrian Rossiter

unread,
Jun 1, 2023, 1:37:29 AM6/1/23
to anti...@googlegroups.com
Hi Roger

On Thu, 1 Jun 2023, Roger Kaufman wrote:
> On 5/31/2023 1:11 PM, Roger Kaufman wrote:
>> This should be the last that needs done with the program if you are waiting
>> to do a build.
>
> I found a bug in canonical when the shuffle indexes feature was used. It
> caused an error in the canonical algorithm but it was the fault of shuffle
> indexes.
>
> conway j^3C -f s | canonical -s a -c c | antiview
>
> The elements were being replaced using raw_ facilities for example
> 'geom.raw_verts() = shuffled_verts;' and this seemed to cause some memory
> problems. Instead they are now cleared and then used the add functions.

Quick reply! You might be able to use the pointer returned by 'data()'

https://cplusplus.com/reference/vector/vector/data/

Adrian Rossiter

unread,
Jun 1, 2023, 1:46:31 AM6/1/23
to anti...@googlegroups.com
Hi Roger

On Wed, 31 May 2023, Roger Kaufman wrote:
> This should be the last that needs done with the program if you are waiting
> to do a build.

Quick reply here too. It will be at least a couple of weeks before I
make the release, and it doesn't matter if it is longer, so just let me
know when you have finished with the changes you want to include.

Roger Kaufman

unread,
Jun 1, 2023, 9:29:51 AM6/1/23
to anti...@googlegroups.com
Hi Adrian,

On 6/1/2023 1:37 AM, Adrian Rossiter wrote:
> Quick reply! You might be able to use the pointer returned by 'data()'
>
> https://cplusplus.com/reference/vector/vector/data/

I tried both of these methods which don't replace the whole vector at
once (which seemed perfectly legal). The problem continued. For some
reason there seems to be a problem after setting the raw data. Note that
a write of the geom after the shuffle function which cause the problem
occurs shows a normal model via off_report. Using clear and the add_
functions work so I left the prior fix in. We can look at this later if
you want.

    Vec3d *p = geom.raw_verts().data();
    for (unsigned int i = 0; i < geom.verts().size(); i++) {
      *p++ = shuffled_verts[i];
      geom.colors(VERTS).set(i, new_cols[i]);
    }

    for (unsigned int i = 0; i < geom.verts().size(); i++) {
      geom.raw_verts()[i] = shuffled_verts[i];
      geom.colors(VERTS).set(i, new_cols[i]);
    }

One thing I noticed, if the edges are shuffled, their order is changed
in the off file. But in antiview they edge numbers remain the same. I
did a simple test. I made cube1.off with edges, then a copy cube2.off
and reversed edge 0 and 1 in the file. The numbers in antiview remain
the same for both files.

Roger


Roger Kaufman

unread,
Jun 2, 2023, 12:10:48 PM6/2/23
to anti...@googlegroups.com
Hi Adrian,

On 6/1/2023 9:29 AM, Roger Kaufman wrote:
> I tried both of these methods which don't replace the whole vector at
> once (which seemed perfectly legal). The problem continued. For some
> reason there seems to be a problem after setting the raw data. Note
> that a write of the geom after the shuffle function which cause the
> problem occurs shows a normal model via off_report. Using clear and
> the add_ functions work so I left the prior fix in. We can look at
> this later if you want.

I looked at this again. The error occurred after a get_dual() and some
of the explicit edges in the dual were missing. If a model is input to
canonical without edges the problem didn't occur.

Looking closer at the shuffled geom, I wasn't doing make_edge() for the
new edges list. Some of the edges were (high, low).

add_edge does an implicit make_edge() so that is why that solved the
problem, I will let that stay the solution in the already pushed program.

I had replaced the raw edges vector in one statement. But had I used
add_edge_raw() it doesn't do an implicit make_edge() so I would have
been in the same boat. add_edge_raw() is used in n_icons but a make_edge
is always being done. off_query uses add_edge_raw() and there is no
make_edge() being done but it may not matter in that case.

Roger

Reply all
Reply to author
Forward
0 new messages