Back to the main page.
Bug 2133 - egi_mff_v2 reading causes global variables to be deleted
Status | REOPENED |
Reported | 2013-04-23 09:11:00 +0200 |
Modified | 2014-06-19 14:41:54 +0200 |
Product: | FieldTrip |
Component: | fileio |
Version: | unspecified |
Hardware: | PC |
Operating System: | Mac OS |
Importance: | P3 normal |
Assigned to: | Colin Davey |
URL: | |
Tags: | |
Depends on: | |
Blocks: | 2466 |
See also: |
Robert Oostenveld - 2013-04-23 09:11:00 +0200
Joe wrote: I just wanted to alert you all to an issue with the EGI MFF Matlab reader code that seems to be due to a bug in Matlab itself, at least as of 2012a (on the Mac at least). The function mff_setup calls the command "javaclasspath(p);" Unfortunately, this Matlab function in turn calls on "clear('java')" which in addition to clearing up the java instances also clears out all the ordinary global variables whether or not they are in scope. So the mff reader will crash any Matlab program that relies on global variables. I'm putting in a workaround into my EP Toolkit as follows: if strcmp(fileFormat,'egi_mff_v2') %workaround for Matlab bug globalList=whos('global'); for i=1:length(globalList) eval(['global ' globalList(i).name ';']); eval(['save EPtemp' globalList(i).name ' ' globalList(i).name ';']); end; end; [hdr]=ft_read_header(fileName,'dataFormat',fileFormat, 'headerformat',fileFormat); [theData]=ft_read_data(fileName,'dataformat',fileFormat, 'headerformat',fileFormat); [eventHdr]=ft_read_event(fileName,'dataformat',fileFormat, 'headerformat',fileFormat,'eventformat',fileFormat); if strcmp(fileFormat,'egi_mff_v2') for i=1:length(globalList) eval(['load EPtemp' globalList(i).name ';']); eval(['delete EPtemp' globalList(i).name '.mat;']); end; end; In other words it temporarily saves all the global variables to disk and then restores them afterwards. You may want to consider doing something similar for mff_setup so that it doesn't affect Matlab programs that call on it. I've also submitted a bugreport to Mathworks so hopefully they can get it fixed.
Robert Oostenveld - 2013-04-23 09:12:44 +0200
I suggest to make a test script to confirm it, and then implement a similar work-around in the ft_read_xxx functions. @Joe, do you by any chance know whether it affects other matlab versions? If you don't know, don't bother. We can check that out. At least for linux we keep all older versions of matlab installed.
Joseph Dien - 2013-04-23 19:46:47 +0200
Created attachment 461 test file you'll need to change the file name to your mff test file.
Joseph Dien - 2013-04-23 19:49:37 +0200
I also found it in 2012a and 2012b. I didn't get a chance to test further back. I'll put the fix in once I get a moment.
Robert Oostenveld - 2013-04-23 21:19:25 +0200
(In reply to comment #2) thanks. I updated the script a little bit and pointed it to a test file on our linux computers. I have not been able to test it yet from my laptop (as I don't have data local), but it should show up on ihttp://fieldtrip.fcdonders.nl/development/dashboard in a few hours. mbp> svn commit test_bug2133.m Adding test_bug2133.m Transmitting file data . Committed revision 8066.
Joseph Dien - 2013-04-24 22:33:58 +0200
Okay, just committed the fix. It works on OS X. I couldn't test on Windows because there is an unrelated problem that keeps it from working on that platform (Windows sees mff files as being folders, not files). I'm going to raise that issue with the EGI team and see if we can find a solution.
Joseph Dien - 2013-09-24 21:34:38 +0200
It turns out the fix only partly works. So the workaround I implemented makes a cell list holding all the global variables prior to the mff setup call, then restores them afterwards as global variables, then delinks all the global variables that were not originally linked to the current scope. However, it turns out that this procedure does not restore the global links to the functions that called the current function. But if you try to redeclare the global variables after the mff call, Matlab registers an error. The workaround therefore has to be to carry out the mff setup at the end of the initial function so that global variables are not needed afterwards. The initial function then terminates and passes control to other functions which can then initialize the global variables as usual. Needless to say, this is all rather messy.
Robert Oostenveld - 2014-02-03 10:07:52 +0100
Hi Joe, Since a new version of mff_v2 is about to be released by EGI, I am looking into the related issues and found this one. I had to make a fix to the test script mac001> svn commit test_bug2133.m Sending test_bug2133.m Transmitting file data . Committed revision 9180. On my desktop mac I was subsequently not able to reproduce it, i.e. the test works fine for me on MATLAB Version: 8.0.0.783 (R2012b) on maci64. But on linux I was able to reproduce it with Version 7.10.0.499 (R2010a) 64-bit (glnxa64). >> test_bug2133 Warning: adding /home/mrphys/roboos/matlab/fieldtrip/external/egi_mff toolbox to your Matlab path Warning: adding /home/mrphys/roboos/matlab/fieldtrip/external/egi_mff/java/MFF-1.0.jar to your Java path > In mff_setup at 16 In ft_read_header at 996 In test_bug2133 at 16 ??? Reference to a cleared variable testvariable. Error in ==> test_bug2133 at 18 assert(exist(testvariable, 'var'));
Robert Oostenveld - 2014-02-03 10:17:49 +0100
Here is another demonstration of the problem, now separate from the script. >> clear all >> global a >> a = 1 a = 1 >> cd matlab/fieldtrip/external/egi_mff/ >> whos Name Size Bytes Class Attributes a 1x1 8 double global >> mff_setup Warning: adding /home/mrphys/roboos/matlab/fieldtrip/external/egi_mff/java/MFF-1.0.jar to your Java path > In mff_setup at 16 >> whos >> the 2nd whos returns nothing, i.e. the global variable disappeared. Note that this is on matlab2010a on 64-bit linux. I did not try any other versions.
Robert Oostenveld - 2014-02-03 10:43:16 +0100
I made a change similar to the one suggested by Joe, except that I store the variables in a "localcopy" structure rather than on disk, and restore them immediately afterwards. roboos@mentat001> svn commit Sending egi_mff/mff_setup.m Transmitting file data . Committed revision 9181. It works in the sense that global variables remain global and in memory. However, the global variable is not visible after "mff_setup", i.e. one again has to do "global xxx" to make the global variable visible. I guess this is due to the variable being cleared, and then restored. The only possible solution I see is to do something with evalin, but that only allows restoring them in the caller and in the base, not at other levels of the function call sequence (i.e. "stack"). Also, it is difficult to ensure that only previously known global variables are restored at the appropriate level.
Robert Oostenveld - 2014-02-27 08:54:18 +0100
The only real solution is that the user calls mff_setup/javaclasspath immediately after starting, but prior to assigning any global variables (either himself, or somewhere in the code). I have added this warning with instructions to mff_setup, which points to this bug. Warning: javaclasspath clears all global variables due to a bug in MATLAB. Please execute /Users/robert/matlab/fieldtrip/external/egi_mff/mff_setup.m immediately after starting MATLAB. See http://bit.ly/1o7QlRk
Robert Oostenveld - 2014-02-27 08:55:16 +0100
(In reply to Robert Oostenveld from comment #10) mbp> svn commit Sending egi_mff/mff_setup.m Transmitting file data . Committed revision 9250.
Robert Oostenveld - 2014-05-14 20:08:54 +0200
closed several of my bugs that have been resolved