UPDATE:  I am able to reproduce this "Premature end of script headers:
wsgihandler.py" error with a slightly modified app based on the image
blog in the web2py book.   I modified it so that images are shown in
the index page, instead of having just the titles listed.

Testing using: ab -kc 100 -t 20 https://domain.com/imageblog/default/index/

If I am simply doing this, there's no error.  BUT when I was running
this test, while simultaneously browsing the website, clicking on
images, etc., then the error appeared, consistently.

Monitoring available RAM while running this test showed system RAM
peeked at about 500MB, still a few hundreds MB available. This is on
the same server as the other app.  VPS. 768MB RAM.  1GB RAM
Burstable.   About 129 apache2 processes running and 11,000 files
openning.

sudo ps aux | grep apache2 | wc
    129    1675   11847

sudo lsof | wc
  10982  106870 1313126


=================================================
Here's a typical Apache Bench result:

Server Software:        Apache/2.2.9
Server Port:            443
SSL/TLS Protocol:       TLSv1/SSLv3,DHE-RSA-AES256-SHA,1024,256

Document Path:          /imageblog/default/index/
Document Length:        13130 bytes

Concurrency Level:      100
Time taken for tests:   20.004 seconds
Complete requests:      588
Failed requests:        15
   (Connect: 0, Receive: 0, Length: 15, Exceptions: 0)
Write errors:           0
Non-2xx responses:      15
Keep-Alive requests:    573
Total transferred:      7875930 bytes
HTML transferred:       7564607 bytes
Requests per second:    29.39 [#/sec] (mean)
Time per request:       3401.991 [ms] (mean)
Time per request:       34.020 [ms] (mean, across all concurrent
requests)
Transfer rate:          384.50 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  912 2146.5      0    7265
Processing:    86 2234 1303.3   2781    4427
Waiting:       85 2136 1281.0   2759    4316
Total:         86 3146 2410.6   3017   10478

Percentage of the requests served within a certain time (ms)
  50%   3017
  66%   3222
  75%   3939
  80%   4029
  90%   7089
  95%   9409
  98%  10098
  99%  10223
 100%  10478 (longest request)

=================================================

Relevant excerpt of db.py:

    db = DAL('postgres://username:password@localhost:5432/imageblog',
pool_size=20)


=================================================
Model:

db.define_table('image',
   Field('title'),
   Field('file', 'upload'))

db.define_table('comment',
   Field('image_id', db.image),
   Field('author'),
   Field('email'),
   Field('body', 'text'))

db.image.title.requires = IS_NOT_IN_DB(db, db.image.title)
db.comment.image_id.requires = IS_IN_DB(db, db.image.id, '%(title)s')
db.comment.author.requires = IS_NOT_EMPTY()
db.comment.email.requires = IS_EMAIL()
db.comment.body.requires = IS_NOT_EMPTY()

=================================================
Controller:

def index():
    images = db().select(db.image.ALL, orderby=db.image.title)
    return dict(images=images)

@auth.requires_login()
def add():
    form = crud.create(db.image, next = URL('index'))
    return dict(form=form)

def show():
    image = db(db.image.id==request.args(0)).select().first()
    form = SQLFORM(db.comment)
    form.vars.image_id = image.id
    if form.accepts(request.vars, session):
        response.flash = 'your comment is posted'
    comments = db(db.comment.image_id==image.id).select()
    return dict(image=image, comments=comments, form=form)

def user():
    """
    exposes:
    http://..../[app]/default/user/login
    http://..../[app]/default/user/logout
    http://..../[app]/default/user/register
    http://..../[app]/default/user/profile
    http://..../[app]/default/user/retrieve_password
    http://..../[app]/default/user/change_password
    use @auth.requires_login()
        @auth.requires_membership('group name')
        @auth.requires_permission('read','table name',record_id)
    to decorate functions that need access control
    """
    return dict(form=auth())


def download():
    """
    allows downloading of uploaded files
    http://..../[app]/default/download/[filename]
    """
    return response.download(request,db)


def call():
    """
    exposes services. for example:
    http://..../[app]/default/call/jsonrpc
    decorate with @services.jsonrpc the functions to expose
    supports xml, json, xmlrpc, jsonrpc, amfrpc, rss, csv
    """
    session.forget()
    return service()


=================================================
View (index.html)

{{extend 'layout.html'}}
<h1>Current Images</h1>

{{for image in images:}}
<div class="entry" style="padding:1em; border-bottom:1px dashed
#999;">
<div class="entrytitle" style="font-size:150%;">{{=A(image.title,
_href=URL("show", args=image.id))}}</div>
<div class="entryimage"><img src="{{=URL('download',
args=image.file)}}"></div>
</div>

{{pass}}

=================================================

Apache's site-enabled/000-default:

<VirtualHost *:80>
  WSGIDaemonProcess web2py user=username group=username \
                           display-name=%{GROUP}
  WSGIProcessGroup web2py
  WSGIScriptAlias / /home/username/web2py/wsgihandler.py

  Alias /awstats-icon/ /usr/share/awstats/icon/
  <Directory /usr/share/awstats/icon>
    Options None
    AllowOverride None
    Order allow,deny
    Allow from all
  </Directory>

  <Directory /home/username/web2py>
    AllowOverride None
    Order Allow,Deny
    Deny from all
    <Files wsgihandler.py>
      Allow from all
    </Files>
  </Directory>

  AliasMatch ^/([^/]+)/static/(.*) \
             /home/username/web2py/applications/$1/static/$2

  <Directory /home/username/web2py/applications/*/static/>
    Options -Indexes
    Order Allow,Deny
    Allow from all
  </Directory>

  <Location /admin>
  Deny from all
  </Location>

  <LocationMatch ^/([^/]+)/appadmin>
  Deny from all
  </LocationMatch>

  CustomLog /var/log/apache2/access.log common
  ErrorLog /var/log/apache2/error.log
</VirtualHost>

Reply via email to