Opened 9 years ago

Last modified 22 months ago

#45582 new defect

grace: xmgrace crashes with SIGSYS in yosemite

Reported by: gezelter@… Owned by: macports-tickets@…
Priority: Normal Milestone:
Component: ports Version:
Keywords: Cc: mojca (Mojca Miklavec), jvianalopes (João Manuel Viana Parente Lopes), basmac, GiovanniBussi (Giovanni)
Port: grace t1lib

Description (last modified by ryandesign (Ryan Carsten Schmidt))

% xmgrace 

Oops! Got SIGSYS

Please use "Help/Comments" to report the bug.
Abort

Change History (13)

comment:1 Changed 9 years ago by gezelter@…

This does not appear to be a duplicate of #42364, as the optimization level in the port file is already set to -O1

Last edited 9 years ago by ryandesign (Ryan Carsten Schmidt) (previous) (diff)

comment:2 Changed 9 years ago by ryandesign (Ryan Carsten Schmidt)

Description: modified (diff)
Summary: xmgrace crashes with SIGSYS in yosemitegrace: xmgrace crashes with SIGSYS in yosemite

Did you do what the error message said ("use 'Help/Comments' to report the bug)"? This sounds like a problem to be reported to the developers.

comment:3 Changed 9 years ago by gezelter@…

I think I may have figured something out - a gdb backtrace points to a t1lib collision between the bundled t1lib in grace and the t1lib installed by macports. This seems to help:

sudo port uninstall grace
sudo port uninstall t1lib
sudo port install grace

It may be that the optimization problem is present in the t1lib port.

comment:4 Changed 9 years ago by basmac

The above suggestion fixed it for us - uninstall grace,t1lib, install grace

comment:5 Changed 9 years ago by mojca (Mojca Miklavec)

Cc: mojca@… added
Port: t1lib added
Version: 2.3.2

comment:6 Changed 9 years ago by mojca (Mojca Miklavec)

In any case grace shouldn't opportunistically link against t1lib and netcdf. Something along the following lines might be needed (untested):

  • Portfile

     
    3737configure.optflags  -O1
    3838configure.pre_args  --prefix=${prefix}/lib
    3939configure.args      --with-helpviewer="${prefix}/bin/openbrowser ${prefix}/share/doc/${name}/`basename %s`" \
    40                     --x-include=${prefix}/include --x-lib=${prefix}/lib
     40                    --x-include=${prefix}/include \
     41                    --x-lib=${prefix}/lib \
     42                    --with-bundled-t1lib \
     43                    --disable-netcdf
    4144
    4245post-destroot {
    4346    xinstall -m 755 -d ${destroot}${prefix}/share/doc
     
    5356
    5457variant netcdf description {Support for NetCDF data files} {
    5558  depends_lib-append        port:netcdf
    56   configure.args-append    --enable-netcdf
     59  configure.args-replace    --disable-netcdf --enable-netcdf
    5760}
    5861
    5962livecheck.type      regex

comment:7 Changed 9 years ago by mojca (Mojca Miklavec)

Plus another comment: making pdflib optional and disabling it by default would make the port distributable. I'm not sure if that's helpful though as I'm not using grace directly, I'm only occasionally using a port that depends on it.

comment:8 in reply to:  3 ; Changed 9 years ago by mjosedelinares@…

Replying to gezelter@…:

I think I may have figured something out - a gdb backtrace points to a t1lib collision between the bundled t1lib in grace and the t1lib installed by macports. This seems to help:

sudo port uninstall grace
sudo port uninstall t1lib
sudo port install grace

It may be that the optimization problem is present in the t1lib port.

I have exactly the same problem, but when I try to do your suggestion it's said "sudo: port: command not found". Even I have tried to uninstall it with "sudo make uninstall" it is said "make: * No rule to make target `uninstall'. Stop.". I don't know what else I can do. I need to be able to use xmgrace.

comment:9 in reply to:  8 Changed 9 years ago by Russell-Jones-OxPhys (Russell Jones)

Replying to mjosedelinares@…:

Replying to gezelter@…:

I think I may have figured something out - a gdb backtrace points to a t1lib collision between the bundled t1lib in grace and the t1lib installed by macports. This seems to help:

sudo port uninstall grace
sudo port uninstall t1lib
sudo port install grace

It may be that the optimization problem is present in the t1lib port.

I have exactly the same problem, but when I try to do your suggestion it's said "sudo: port: command not found". Even I have tried to uninstall it with "sudo make uninstall" it is said "make: * No rule to make target `uninstall'. Stop.". I don't know what else I can do. I need to be able to use xmgrace.

It sounds like you don't have MacPorts installed correctly. See https://www.macports.org/install.php The instructions are for installing via MacPorts, not directly from the source.

Last edited 9 years ago by Russell-Jones-OxPhys (Russell Jones) (previous) (diff)

comment:10 Changed 9 years ago by marc.octavo@…

I had the same problem and solved it adding +universal variant

sudo port install grace +universal

comment:11 Changed 9 years ago by phillicl@…

This worked for me as well

comment:12 Changed 8 years ago by mf2k (Frank Schima)

Cc: jvianalopes@… barry.j.mcinnes@… giovanni.bussi@… added

Cc people from duplicates #47122 and #49893.

comment:13 Changed 22 months ago by chuckcranor

I have figured out why grace crashes at startup (unless you compile -O1 or less). The t1lib is triggering a clang code generation bug.

There is also a malloc buffer overflow in t1lib that causes issues on OSX.

Here are the details from an email I posted elsewhere:

there are two bugs in fonts/t1lib that cause grace to crash on OSX:

  1. compiler bug in some versions of clang when compiling with "-O2" ... this appears to have been fixed somewhere between clang-11 and clang-12. it works ok with "-O1".
  1. one case of t1lib trying to be clever and instead writing past end of malloc'd buffer (which the OSX malloc did not like at all). the address sanitizer helped pinpoint this.

For 1, the t1lib is trying to roll its own optmized memcpy() using this macro in lib/type1/objects.h:

 #define  LONGCOPY(dest,source,bytes) { \
     register LONG *p1 = (LONG *)dest;  register LONG *p2 = (LONG *)source; \
     register int count = (bytes) / sizeof(LONG); \
     while (--count >= 0) *p1++ = *p2++; }

they explain (in lib/type1/objects.c) they are doing this because there is no standarized portable memory copy routine (e.g. memcpy() vs bcopy()). maybe that was true in 1991 when this code was written, but i think pretty much everyone has memcpy() now?

At any rate, some versions of "clang -O2" choke on LONGCOPY() and produce incorrect code. I've got a 49 line test C program that reproduces the issue (see attached xalloc-test.c):

        % clang-11 -O1 -o alloc-test xalloc-test.c 
        % ./alloc-test 
        Result CORRECT!
        % clang-11 -O2 -o alloc-test xalloc-test.c
        % ./alloc-test
        Result FAILED! (0 != 0x80)
        % clang-12 -O2 -o alloc-test xalloc-test.c
        % ./alloc-test
        Result CORRECT!
        % 

I think the solution is to assume that memcpy() is going to be available and have LONGCOPY() use memcpy() rather than its custom copy.

For 2, the issue is in lib/type1/regions.c where it allocates "(ymax - iy) * sizeof(pel)" bytes of extra data using malloc and then uses LONGCOPY() like this:

/* 
We must round up (ymax - iy) so we get the ceiling of the number of
longs.  The destination must be able to hold these extra bytes because 
Allocate() makes everything it allocates be in multiples of longs.
*/
       LONGCOPY(&r[1], xvalues, (ymax - iy) * sizeof(pel) + sizeof(LONG) - 1);

they've incorrectly computed the ceiling by just adding "sizeof(LONG) - 1" (need to mask off the low bits by "~(sizeof(LONG) - 1)").

with those fixes in, I can run grace on all the examples that it installs (using the "dotest" script there) on OSX without grace crashing with everything compiled -O2.

xalloc test program source:

#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct xobject {
    int flag;
};

#define  LONGCOPY(dest,source,bytes) do {                                  \
    long *p1 = (long *)dest;                                               \
    long *p2 = (long *)source;                                             \
    int count = (bytes) / sizeof(long);                                    \
    while (--count >= 0)                                                   \
        *p1++ = *p2++;                                                     \
} while(0)

struct xobject *t1_Allocate(int size, struct xobject *xtemplate) {
    struct xobject *r;
 
    r = (struct xobject *) malloc(size);
    if (r == NULL) errx(1, "malloc abort");
 
#if 1
    LONGCOPY(r, xtemplate, size);
#else
    memcpy(r, xtemplate, size);
#endif
    r->flag &= ~(0x01);
    return(r);
}

int main(int argc, char **argv) {
    struct xobject *xo, *xo2;

    xo = malloc(56);
    memset(xo, 0, 56);
    xo->flag = 0x80;

    xo2 = t1_Allocate(56, xo);

    if (xo2->flag == 0x80) {
        fprintf(stderr, "Result CORRECT!\n");
    } else {
        fprintf(stderr, "Result FAILED! (%#x != 0x80)\n", xo2->flag);
    }
   exit(0);
}

Note: See TracTickets for help on using tickets.