Arc Forumnew | comments | leaders | submitlogin
1 point by evanrmurphy 9 hours ago | link | parent | on: Permission Denied; errno=13?!

I was having a duplicate of system42's problem, and commenting out line 14 fixed it for me. Thank you, aw!

dito

Thanks again.

Happy to help.

Oh, yes, quoted-unquotes are done pretty often.

  $ grep -c "'," {arc,code,html,srv,app,news}.arc
  arc.arc:17
  code.arc:1
  html.arc:6
  srv.arc:9
  app.arc:1
  news.arc:7
For example, the Arc built-in obj is a macro that makes a hash table with automatically-quoted keys.

  arc> (= h (obj a 1 b 2))
  #hash((b . 2) (a . 1))
  arc> (h 'a)
  1
  arc> (h 'b)
  2
It's defined like so:

  (mac obj args
    `(listtab (list ,@(map (fn ((k v))
                             `(list ',k ,v)) ; note we unquote k, then quote it
                                             ; so we're quoting the value of k
                           (pair args)))))
That way, the above (obj a 1 b 2) expands into

  (listtab (list (list 'a 1) (list 'b 2)))

Very instructive. Thank you for doing such a thorough analysis.

',r from your snippet

  (mac rdefop (r)
    `(defop ,r req (rpage ',r)))
was a realization for me. Never thought of quoting a comma'd symbol in a backquoted expression before, but I like knowing it's possible. Do you find yourself doing this much, or is there usually something simpler like aw's solution available to make it unnecessary?

You don't really need eval in the macro. In the original,

  (each r routes*
    (rdefop r))
macroexpands into

  (each r routes*
    (defop r req (pr "Schedule for " r " goes here")))
without evaluating what r is bound to --- you'll just get an /r handler.

So, using eval makes sure r gets evaluated. But you do this haphazardly between two points:

  (mac rdefop (rs)
    (eval `'(defop ,(fromstring  rs (read)) req
                  (rpage ,rs))))

  (each r routes*
    (eval `(rdefop ,r)))
We only need to eval once.

  (= routes* '(10a 10b 15a 20a 20b 30a 30b 30c 40a 59u))

  (def rpage (r)
    (pr r))

  (mac rdefop (r)
    `(defop ,r req (rpage ',r)))

  (each r routes*
    (eval `(rdefop ,r)))
Thus, instead of doing (defop r), it's kind of like we're doing (defop (eval r)). That is, instead of expanding into

  (defop r req (rpage 'r))
we're expanding into

  (defop 10a req (rpage '10a)) ; when r == '10a
  (defop 10b req (rpage '10b)) ; when r == '10b
  ; etc
We could've done the eval inside the macro, too, but that's often a sign you're doing something wrong --- macros are usually there to not evaluate their arguments. So we should probably use a function.

However, defop itself is a macro, so the first parameter (the op's name) won't be evaluated regardless. We still need eval.

  (= routes* '(10a 10b 15a 20a 20b 30a 30b 30c 40a 59u))

  (def rpage (r)
    (pr r))

  (def rdefop (r)
    (eval `(defop ,r req (rpage ',r))))

  (each r routes*
    (rdefop r))
Since this approach seems to require eval regardless, we should just look for a better solution. aw's works nicely.

Some other nitpicks over your rewrite (hey, you asked!):

1) Unless you need strings for some reason, you can probably default to symbols (they're a bit easier to use).

  ; Instead of

  (= routes* '("10a" "10b" "15a" "20a" "20b" "30a" "30b" "30c" "40a" "59u"))

  ; we could use

  (= routes* '(10a 10b 15a 20a 20b 30a 30b 30c 40a 59u))
2) Proper spacing & indentation saves lives. :)

  ; Instead of

  (defop shuttle req
    (each r routes* (link r)(nbsp)))

  ; why not

  (defop shuttle req
    (each r routes* (link r) (nbsp)))

  ; or even

  (defop shuttle req
    (each r routes*
      (link r)
      (nbsp)))
3) Though using symbols renders this point moot, fromstring is unnecessary to simply (read) from a string, since Arc's definition of read is

  (def read ((o x (stdin)) (o eof nil))
    (if (isa x 'string) (readstring1 x eof) (sread x eof)))
So, instead of

  (fromstring rs (read))
you can use

  (read rs)
If your goal is just to turn a string into a symbol, you should use

  (sym rs)
This is an important distinction. e.g.,

  arc> (sym "abc")
  abc
  arc> (read "abc")
  abc
  arc> (sym "(a b c)")
  |(a b c)|
  arc> (type that)
  sym
  arc> (read "(a b c)")
  (a b c)
  arc> (type that)
  cons

I am not sure. It didn't work for me when I took it out.

Why do you need the eval in rdefop? What am I missing?

Curious if any of the more advanced folks on this board can show how to properly do the above code (such that I can learn from). Or is the above code not so bad after all? Thanks.

It's standard to refer to a git commit id by only the first few digits of the number.

So don't worry! You can call it merely "601d2" instead ;)


Very helpful, all of you. Thanks again for your time and the great advice.

@conanite This will definitely help me take advantage of the repl better in the future.

@thaddeus

  > I think you intended to do this: [...]
Yes, exactly!

  > And don't ask me why the following works - it's a brutal hack! [...]
Thanks for posting this. I'm realizing more and more how much better it is to have a brutal hack that works than some thoughtful code that doesn't.

@aw I used a variation of your code (with ?route=) in my solution. Much more elegant than what I was trying to do, thank you.


A quick way to figure out what's going wrong is to try it at the repl ...

  arc> (= routes* '(10a 10b 15a 20a 20b 30a 30b 30c 40a 59u))
  (10a 10b 15a 20a 20b 30a 30b 30c 40a 59u)
  arc> (each r routes* (link r (nbsp)))
  &nbsp;<a href="&nbsp;">10a</a>&nbsp;<a href="&nbsp;">10b</a>&nbsp;<a href="&nbsp;">15a</a>&nbsp;<a href="&nbsp;">20a</a>&nbsp;<a href="&nbsp;">20b</a>&nbsp;<a href="&nbsp;">30a</a>&nbsp;<a href="&nbsp;">30b</a>&nbsp;<a href="&nbsp;">30c</a>&nbsp;<a href="&nbsp;">40a</a>&nbsp;<a href="&nbsp;">59u</a>nil
  arc> 
The <a href="&nbsp;"> stands out like a sore thumb in this case.

Wow, Haskell. The chapters on "self-similar music" and "an algebra of music" look particularly interesting, I'm going to enjoy them. Thanks for the link.

my programmer senses tingle and I find myself wanting to abstract things away - you hit the nail on the head there. What's more, I'm sure there's meaning in those patterns if we could only make them explicit - listening to music is sometimes listening to a conversation in a mostly-foreign language - words here and there that you recognize, you suspect that something meaningful is being communicated, but it's just beyond your grasp.

don't let the text-only nature of Arc discourage you - no chance, I'm too far gone for that.


I think you intended to do this:

  (defop shuttle req
    (each r routes* (link r)(nbsp)))
And don't ask me why the following works - it's a brutal hack!

  (= routes* '("10a" "10b" "15a" "20a" "20b" "30a" "30b" "30c" "40a" "59u"))

  (defop shuttle req
    (each r routes* (link r)(nbsp)))

  (def rpage (r)
     (pr r))

  (mac rdefop (rs)
    (eval `'(defop ,(fromstring  rs (read)) req 
	          (rpage ,rs))))

  (each r routes*
    (eval `(rdefop ,r)))

[edit] corrected link as per aw's post.

For your second question, we could work on getting your macro defining macro to work, if you wanted. For this particular task, personally I'd do something simpler: I'd make the link like this:

  (link r (+ "/schedule?route=" r))
and then have

  (defop schedule req
    (pr "Schedule for " (arg req "route") " goes here"))

The second argument to "link" specifies the URL that the link goes to. So you might try

  (link r (+ "/" r))
which will make the URL "/10a" for route 10a.

If all your pages are at the same level and using just "10a" for the URL would work OK, then you could use

  (link r)
because if you call "link" with one argument it will be used for both the text and the URL.

"If you aren't using the C foreign function interface, of course."

Yeah that phase actually performs stemming as well using the FFI. For a long time that was my prime suspect, but I have never been able to get stemming to segfault in isolation, either within arc or from a C program. And I have been able to get my program to segfault without the stemming.

You're right, I'll take another stab at a test case. And I'll not try so hard to make it tiny.


If you do the exact same data import with the program in the same initial state, will it segfault again? (You may need to add code to record e.g. the contents of your data files prior to the import and what exactly is being imported).

Or, if you start in a known state and run fifty data imports in a row, can you get it to segfault?

Arc is not supposed to be able to segfault MzScheme. To MzScheme, Arc is just a big program written in Scheme. And MzScheme running Scheme programs is not supposed to segfault.

(If you aren't using the C foreign function interface, of course. A messed up pointer can cause unrelated code to blow up later. So the above paragraph is true if you are only using libraries which are either written in Scheme [and/or Arc, since Arc is written in Scheme] or part of the official MzScheme distribution).

It's true that the PLT folks certainly don't want to be debugging your Arc program, but they do want to be able to get MzScheme to work. And the way to enable them to do that is to give them a test case that they can run to see the segfault. If you can. Even if it is thousands of lines of code and megabytes of data. If you give them a shell script "diedie" that runs a MzScheme program (that runs Arc and loads your program and imports your data) that segfaults, then you make it possible for them to find out what is causing the segfault.


You know, those steps were approximately what I've been trying to follow :) I thought I had boiled it down to a test case, but now I'm betrayed by it. Betrayed! :)

I don't really have a problem posting the code, but it'll be a huge ball of mud since it includes arc as well. I'm not sure the PLT folks will want to mess with that to find a bug that only occurs sometimes and may well be arc's fault.

It doesn't seem as easy as replaying a request. I encounter the error during a periodic data import phase in my server. It's not being triggered by a specific request. And it doesn't happen everytime the program goes into that phase. Sometimes I see the segfault 6 times a day (the phase runs once an hour), and sometimes everything's peachy for 3 days.

Shelling out to perl is a good idea. I think I'll try using your hack for that.


If you want to pursue this, here are some steps...

If your server dies when running live, you can get it to die yourself by feeding it the same input as it gets from your browser and/or your users.

Now you have a large and complex program that you can get to segfault by feeding it some large and complex set of data.

Then you can run the same program with the same data in the same version of MzScheme on your personal computer, and see if it segfaults there as well. (If not, perhaps it is an OS library problem).

If it also segfaults on your computer, that's good news, you're on your way to track it down.

You can ask on the PLT mailing list what debugging information they'd like to see to track down a segfault.

And, if you feel like it, you can try removing chunks of your program to find a smaller test case that triggers the segfault.

If you can get it to segfault with chunks of code that are non-proprietary to you, that you don't mind publishing, then you can even post a link to a zip or a tar containing the code and the input data and instructions on how to trigger the segfault. Then it would be possible for one of the PLT people to find their bug, even if you have to apologize that your test case is so giant because you couldn't find a smaller test case to trigger the bug.

Alternatively, if this regex code is something you could push off to do in another process (such as by shelling out to Perl to do the regex stuff for you), you could try that.


You know, that was one reason I was inclined to move to v372 - version 4 is a huge change. If PLT seems less mature now because of these errors I wanted to treat pre-4.0 and post-4.0 as separate beasts.

But I gave up on porting json.ss to v372 (it's prob something really simple; I'll mail you a file just FYI) and now I'm going to go fix non-stability issues on readwarp for a couple of days..


It's dying in the same phase as before. I emit prints before and after the regex-heavy phase. That's where it's dying. The error is still "SIGSEGV fault on 0x10000084"[1]

I mean, clearly I'm not capturing some aspect of the bug since it's not showing up in the sample test. It seems simpler to assume there's one bug in PLT scheme rather than two, and that we just don't fully understand it.

[1] update: I suppose that's just some error handler


Not sure if I'm quite following you. I think you're saying that you're getting segfaults on your new server even though your sample regex test is working; but if that's true, how do you know that it's bug C, that the segfaults are coming from the regexs?

Argh, my new server died. So Bug C is alive and well even though the scheme sample I isolated works.

Check this out for some great ideas about doing computer music: http://plucky.cs.yale.edu/cs432/HSoM-V0.14.pdf

Correction: that's v4.2.1 on 32-bit fedora 8 on EC2.

Argh, it replaced the '=' with '=3D'.

Presumably subscribers will see the correct link in their email.


When I do the second example, I get results similar to yours.

I actually looked at Rainbow just yesterday and noticed you doing this. XD Immediately I wondered whether you'd put a link up here, and here it is.

Anyway, I think this is a great use of Arc. Whenever I'm manipulating something that has a lot of patterns in it, my programmer senses tingle and I find myself wanting to abstract things away. That way, the project is smaller and easier to wrangle, and I can't make small mistakes writing out all the patterns myself. Music is a perfect example of this, as you say.

As someone who only knows sheet music well enough to count my way eventually to the right keys on the piano, I'd like to volunteer that s2/4/5 jumps off the page for me even better than the sheet music does, since I don't have sharps and flats to worry about. In fact, I think I'd be more confident playing that opening motif if I put the Arc version in front of me. XD Chances are I just don't know what I'm missing, but still I hope you don't let the text-only nature of Arc discourage you. ^_^

More