From: Sam H. <sh...@ma...> - 2005-09-10 13:32:27
|
On Sep 9, 2005, at 21:03, Davide P.Cervone wrote: >>>>> (I'm not sure why it is necessary to make a local variable for >>>>> LOG, but at least it works now.) >>>> We want WW to be thread safe, so that when we port it to Apache >>>> 2 (my next major project), people can run it under the threaded >>>> MPM. >>> OK. I'll keep that in mind as I work on other parts. I guess >>> that means most of the other file access code will have to be >>> modified similarly. >> Most of the file access code already uses lexical variables. > > A quick grep in webwork2/lib/WeBWorK turned up the following file > references that don't seem to be localized: > > [snip -- 27 examples of thread-unsafe filehandles] > > So it looks like there are still a few out there to be taken care of. Yikes -- it appears so. In addition to those places, we should look at the places where the filehandle's typeglob has been localized before the open() call -- these are threadsafe, but dynamic scope isn't really what we want here. Also, here are the file-scoped lexicals that are hanging around, potentially causing similar problems. (That is, if they get modified. If they're just being used as constants, then in most cases we can replace them with 'use constant', or maybe use a real constant class that uses a tied scalar.) Fortunately, most of it is in WebworkWebservice, which isn't production code yet, or in PG, where I'm not sure if it's a problem, since every problem has its own environment. -sam [sh002i@devel] work$ grep -r '^my\b' webwork2/lib pg/lib webwork2/lib/PSH.pm:my() variables. webwork2/lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm:my % uploadDir = ( webwork2/lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm:my $UPDATE_SETTINGS_BUTTON = "Update settings and refresh page"; # handle submit value idiocy webwork2/lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm:my % problib; ## filled in in global.conf webwork2/lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm:my % ignoredir = ( webwork2/lib/WebworkWebservice/MathTranslators.pm:my $debugOn = 1; webwork2/lib/WebworkWebservice/MathTranslators.pm:my $PASSWORD = $WebworkWebservice::PASSWORD; webwork2/lib/WebworkWebservice/MathTranslators.pm:my $TEMPDIRECTORY = $ce->{webworkDirs}->{htdocs_temp}; webwork2/lib/WebworkWebservice/MathTranslators.pm:my $TEMP_BASE_URL = $ce->{webworkURLs}->{htdocs_temp}; webwork2/lib/WebworkWebservice/MathTranslators.pm:my $externalLatexPath = $ce->{externalPrograms}->{latex}; webwork2/lib/WebworkWebservice/MathTranslators.pm:my $externalpdflatexPath = $ce->{externalPrograms}->{pdflatex};; webwork2/lib/WebworkWebservice/MathTranslators.pm:my $tmp_directory_permission = $Global::tmp_directory_permission; webwork2/lib/WebworkWebservice/MathTranslators.pm:my $numericalGroupID =$Global::numericalGroupID; # group ID for webadmin webwork2/lib/WebworkWebservice/RenderProblem.pm:my $debugXmlCode=1; # turns on the filter for debugging XMLRPC and SOAP code webwork2/lib/WebworkWebservice/RenderProblem.pm:my $COURSE_TEMP_DIRECTORY = $ce->{courseDirs}->{html_tmp}; webwork2/lib/WebworkWebservice/RenderProblem.pm:my $COURSE_TEMP_URL = $HOSTURL.$ce->{courseURLs}-> {html_tmp}; webwork2/lib/WebworkWebservice/RenderProblem.pm:my $pgMacrosDirectory = $ce->{pg_dir}.'/macros/'; webwork2/lib/WebworkWebservice/RenderProblem.pm:my $macroDirectory =$ce->{courseDirs}->{macros}.'/'; webwork2/lib/WebworkWebservice/RenderProblem.pm:my $templateDirectory = $ce->{courseDirs}->{templates}; webwork2/lib/WebworkWebservice/RenderProblem.pm:my % PG_environment = $ce->{pg}->{specialPGEnvironmentVars}; pg/lib/AnswerHash.pm:my %fields = ( 'score' => undef, pg/lib/Circle.pm:my %fields =( pg/lib/Complex1.pm:my ( $i, $ip2, %logn ); pg/lib/Complex1.pm:my @trig = qw( pg/lib/Complex1.pm:my $package = 'Complex1'; pg/lib/Complex1.pm:my $display = 'cartesian'; # Default display format pg/lib/Complex1.pm:my $eps = 1e-14; # Epsilon pg/lib/Complex1.pm:my %gcd; pg/lib/Fraction.pm:my %fields = ( pg/lib/Fun.pm:my $GRAPH_REFERENCE = "WWPlot"; pg/lib/Fun.pm:my $FUNCTION_REFERENCE = "Fun"; pg/lib/Fun.pm:my %fields =( pg/lib/Label.pm:my %fields =( pg/lib/List.pm:my %fields = ( pg/lib/PGrandom.pm:my $multiplier = 69069; pg/lib/PGrandom.pm:my $translate = 1; pg/lib/PGrandom.pm:my $modulus = 2**32; pg/lib/Parser.pm:my $pkg = "Parser"; pg/lib/Regression.pm:my $nan= "NaN"; pg/lib/Units.pm:my %fundamental_units = ('factor' => 1, pg/lib/Units.pm:my $PI = 4*atan2(1,1); pg/lib/Units.pm:my %known_units = ('m' => { pg/lib/Value.pm:my $pkg = 'Value'; pg/lib/VectorField.pm:my $GRAPH_REFERENCE = "WWPlot"; pg/lib/VectorField.pm:my $VECTORFIELD_REFERENCE = "VectorField"; pg/lib/VectorField.pm:my %fields =( pg/lib/WWPlot.pm:my $last_image_number=0; #class variable. Keeps track of how many images have been made. pg/lib/WWPlot.pm:my %fields = ( # initialization only!!! pg/lib/ww_strict.pm:my %bitmask = ( pg/lib/ww_strict.pm:my $default_bits = bits(qw(refs subs vars)); pg/lib/Parser/Context.pm:my $pkg = "Parser::Context"; pg/lib/Parser/Context.pm:my $userContext; pg/lib/Parser/Context/Default.pm:my $infinity = Value::Infinity->new(); pg/lib/Parser/Context/Functions.pm:my %Category = ( pg/lib/Parser/Legacy/LimitedNumeric.pm:my $context = $Parser::Context::Default::context{Numeric}->copy; pg/lib/Parser/Legacy/Numeric.pm:my $context = $Parser::Context::Default::context{Numeric}->copy; pg/lib/Parser/List/Vector.pm:my $ijk_string = ['i','j','k','0']; pg/lib/Parser/List/Vector.pm:my $ijk_TeX = ['\boldsymbol {i}','\boldsymbol{j}','\boldsymbol{k}','\boldsymbol(0)']; pg/lib/Value/AnswerChecker.pm:my %tth_delim = ( pg/lib/Value/AnswerChecker.pm:my @ans_defaults = (showCoodinateHints => 0, checker => sub {0}); pg/lib/Value/Complex.pm:my $pkg = 'Value::Complex'; pg/lib/Value/Context.pm:my $pkg = "Value::Context"; pg/lib/Value/Formula.pm:my $pkg = 'Value::Formula'; pg/lib/Value/Formula.pm:my $UNDEF = bless {}, "UNDEF"; pg/lib/Value/Infinity.pm:my $pkg = 'Value::Infinity'; pg/lib/Value/Interval.pm:my $pkg = 'Value::Interval'; pg/lib/Value/List.pm:my $pkg = 'Value::List'; pg/lib/Value/Matrix.pm:my $pkg = 'Value::Matrix'; pg/lib/Value/Point.pm:my $pkg = 'Value::Point'; pg/lib/Value/Real.pm:my $pkg = 'Value::Real'; pg/lib/Value/Set.pm:my $pkg = 'Value::Set'; pg/lib/Value/String.pm:my $pkg = 'Value::String'; pg/lib/Value/Union.pm:my $pkg = 'Value::Union'; pg/lib/Value/Union.pm:my %subCall = ( pg/lib/Value/Vector.pm:my $pkg = 'Value::Vector'; pg/lib/Value/Vector.pm:my $ijk_string = ['i','j','k','0']; pg/lib/Value/Vector.pm:my $ijk_TeX = ['\boldsymbol{i}','\boldsymbol {j}','\boldsymbol{k}','\boldsymbol{0}']; pg/lib/Value/WeBWorK.pm:my @wwEvalFields = qw( pg/lib/WeBWorK/PG/Translator.pm:my %shared_subroutine_hash = ( |