{"action":"created","issue":{"url":"https://api.github.com/repos/Kozea/Radicale/issues/253","labels_url":"https://api.github.com/repos/Kozea/Radicale/issues/253/labels{/name}","comments_url":"https://api.github.com/repos/Kozea/Radicale/issues/253/comments","events_url":"https://api.github.com/repos/Kozea/Radicale/issues/253/events","html_url":"https://github.com/Kozea/Radicale/issues/253","id":54331016,"number":253,"title":"PUT requests are hanging","user":{"login":"somecallmemike","id":3587741,"avatar_url":"https://avatars.githubusercontent.com/u/3587741?v=3","gravatar_id":"","url":"https://api.github.com/users/somecallmemike","html_url":"https://github.com/somecallmemike","followers_url":"https://api.github.com/users/somecallmemike/followers","following_url":"https://api.github.com/users/somecallmemike/following{/other_user}","gists_url":"https://api.github.com/users/somecallmemike/gists{/gist_id}","starred_url":"https://api.github.com/users/somecallmemike/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/somecallmemike/subscriptions","organizations_url":"https://api.github.com/users/somecallmemike/orgs","repos_url":"https://api.github.com/users/somecallmemike/repos","events_url":"https://api.github.com/users/somecallmemike/events{/privacy}","received_events_url":"https://api.github.com/users/somecallmemike/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-01-14T14:56:55Z","updated_at":"2015-01-14T15:46:29Z","closed_at":"2015-01-14T15:24:51Z","body":"We are trying to use Radicale with database storage in an environment with about 100 users, and after turning it up it the system seems to be hanging constantly on PUT requests.  The logs are not describing any kind of failure, rather the PUT request shows up and then no other requests seem to be able to be handled afterwards.\r\n\r\nHere is an example log:\r\n\r\n```\r\n2015-01-14 08:36:25,534 - INFO: PUT request at /user@domain.net/personal.vcf/.vcf received\r\n2015-01-14 08:36:25,535 - DEBUG: Request headers:\r\n{'CONTENT_LENGTH': '35',\r\n 'CONTENT_TYPE': 'text/vcard',\r\n 'GATEWAY_INTERFACE': 'CGI/1.1',\r\n 'HTTP_AUTHORIZATION': 'Basic cGF0cml3ZWJAd29sZm5ldC5uZXQ6WkJONUpNUA==',\r\n 'HTTP_CONNECTION': 'Close',\r\n 'HTTP_HOST': 'dav.domain.net',\r\n 'HTTP_USER_AGENT': 'MyRoundcube PHP/5.0',\r\n 'PATH_INFO': '/user@domain.net/personal.vcf/.vcf',\r\n 'QUERY_STRING': '',\r\n 'REMOTE_ADDR': '1.2.3.4',\r\n 'REMOTE_HOST': '',\r\n 'REQUEST_METHOD': 'PUT',\r\n 'SCRIPT_NAME': '',\r\n 'SERVER_NAME': 'server.domain.net',\r\n 'SERVER_PORT': '5232',\r\n 'SERVER_PROTOCOL': 'HTTP/1.1',\r\n 'SERVER_SOFTWARE': 'WSGIServer/0.1 Python/2.6.6',\r\n 'wsgi.errors': <open file '<stderr>', mode 'w' at 0x7f14c70aa1e0>,\r\n 'wsgi.file_wrapper': <class wsgiref.util.FileWrapper at 0x7f14c6f55ad0>,\r\n 'wsgi.input': <socket._fileobject object at 0x1a19ad0>,\r\n 'wsgi.multiprocess': False,\r\n 'wsgi.multithread': True,\r\n 'wsgi.run_once': False,\r\n 'wsgi.url_scheme': 'http',\r\n 'wsgi.version': (1, 0)}\r\n2015-01-14 08:36:25,535 - DEBUG: Sanitized path: /user@domain.net/personal.vcf/.vcf\r\n2015-01-14 08:36:25,535 - DEBUG: Connecting to IMAP server dav.domain.net:993.\r\n2015-01-14 08:36:25,611 - DEBUG: Authenticated IMAP user user@domain.net via imap.domain.net.\r\n2015-01-14 08:36:25,617 - DEBUG: Rights type 'owner_only'\r\n2015-01-14 08:36:25,617 - DEBUG: Test if 'user@domain.net:user@domain.net/personal.vcf' matches against '.+:^user@domain.net(/.*)?$' from section 'rw'\r\n2015-01-14 08:36:25,618 - DEBUG: Section 'rw' matches\r\n2015-01-14 08:36:25,618 - DEBUG: user@domain.net has read access to collection user@domain.net/personal.vcf/\r\n2015-01-14 08:36:25,618 - DEBUG: Rights type 'owner_only'\r\n2015-01-14 08:36:25,618 - DEBUG: Test if 'user@domain.net:user@domain.net/personal.vcf' matches against '.+:^user@domain.net(/.*)?$' from section 'rw'\r\n2015-01-14 08:36:25,618 - DEBUG: Section 'rw' matches\r\n2015-01-14 08:36:25,618 - DEBUG: user@domain.net has write access to collection user@domain.net/personal.vcf/\r\n2015-01-14 08:36:25,619 - DEBUG: Request content:\r\nBEGIN:VCARD\r\nVERSION:3.0\r\nN:Vaughan;Barb;;;\r\nFN:Barb Vaughan\r\nEMAIL;TYPE=INTERNET;TYPE=OTHER:testuser@testdomain.net\r\nUID:12661E97-F4CF8735-E0BA5479\r\nEND:VCARD\r\n```\r\n\r\nHere is our config:\r\n\r\n```\r\n# -*- mode: conf -*-\r\n# vim:ft=cfg\r\n\r\n# Config file for Radicale - A simple calendar server\r\n#\r\n# Place it into /etc/radicale/config (global)\r\n# or ~/.config/radicale/config (user)\r\n#\r\n# The current values are the default ones\r\n\r\n\r\n[server]\r\n# CalDAV server hostnames separated by a comma\r\n# IPv4 syntax: address:port\r\n# IPv6 syntax: [address]:port\r\n# For example: 0.0.0.0:9999, [::]:9999\r\n# IPv6 adresses are configured to only allow IPv6 connections\r\nhosts = 0.0.0.0:5232\r\n# Daemon flag\r\ndaemon = False\r\n# File storing the PID in daemon mode\r\npid =\r\n# SSL flag, enable HTTPS protocol\r\nssl = True\r\n# SSL certificate path\r\ncertificate = /usr/local/admin/ssl.crt/mdc.crt\r\n# SSL private key\r\nkey = /usr/local/admin/ssl.key/mdc.key\r\n#CAfile = /usr/local/admin/ssl.ca/mdc.ca\r\n# SSL Protocol used. See python's ssl module for available values\r\nprotocol = PROTOCOL_SSLv23\r\n# Ciphers available. See python's ssl module for available ciphers\r\nciphers =\r\n# Reverse DNS to resolve client address in logs\r\ndns_lookup = False\r\n# Root URL of Radicale (starting and ending with a slash)\r\nbase_prefix = /\r\n# Possibility to allow URLs cleaned by a HTTP server, without the base_prefix\r\ncan_skip_base_prefix = False\r\n# Message displayed in the client when a password is needed\r\nrealm = Radicale - Password Required\r\n\r\n\r\n[encoding]\r\n# Encoding for responding requests\r\nrequest = utf-8\r\n# Encoding for storing local collections\r\nstock = utf-8\r\n\r\n\r\n[auth]\r\n# Authentication method\r\n# Value: None | htpasswd | IMAP | LDAP | mysql | PAM | courier | http | remote_user | custom\r\ntype = IMAP\r\n\r\n# Custom authentication handler\r\ncustom_handler =\r\n\r\n# Htpasswd filename\r\nhtpasswd_filename = /etc/radicale/users\r\n# Htpasswd encryption method\r\n# Value: plain | sha1 | crypt\r\nhtpasswd_encryption = crypt\r\n\r\n# LDAP server URL, with protocol and port\r\nldap_url = ldap://localhost:389/\r\n# LDAP base path\r\nldap_base = ou=users,dc=example,dc=com\r\n# LDAP login attribute\r\nldap_attribute = uid\r\n# LDAP filter string\r\n# placed as X in a query of the form (&(...)X)\r\n# example: (objectCategory=Person)(objectClass=User)(memberOf=cn=calenderusers,ou=users,dc=example,dc=org)\r\n# leave empty if no additional filter is needed\r\nldap_filter =\r\n# LDAP dn for initial login, used if LDAP server does not allow anonymous searches\r\n# Leave empty if searches are anonymous\r\nldap_binddn =\r\n# LDAP password for initial login, used with ldap_binddn\r\nldap_password =\r\n# LDAP scope of the search\r\nldap_scope = OneLevel\r\n\r\n# IMAP Configuration\r\nimap_hostname = imap.domain.tld\r\nimap_port = 993\r\nimap_ssl = True\r\n\r\n# PAM group user should be member of\r\npam_group_membership =\r\n\r\n# Path to the Courier Authdaemon socket\r\ncourier_socket =\r\n\r\n# HTTP authentication request URL endpoint\r\nhttp_url =\r\n# POST parameter to use for username\r\nhttp_user_parameter =\r\n# POST parameter to use for password\r\nhttp_password_parameter =\r\n\r\n\r\n[git]\r\n# Git default options\r\ncommitter = Radicale <radicale@example.com>\r\n\r\n\r\n[rights]\r\n# Rights backend\r\n# Value: None | authenticated | owner_only | owner_write | from_file | custom\r\ntype = owner_only\r\n\r\n# Custom rights handler\r\ncustom_handler =\r\n\r\n# File for rights management from_file\r\nfile = ~/.config/radicale/rights\r\n\r\n\r\n[storage]\r\n# Storage backend\r\n# Value: filesystem | multifilesystem | database | custom\r\ntype = database\r\n\r\n# Custom storage handler\r\ncustom_handler =\r\n\r\n# Folder for storing local collections, created if not present\r\nfilesystem_folder = ~/.config/radicale/collections\r\n\r\n# Database URL for SQLAlchemy\r\n# dialect+driver://user:password@host/dbname[?key=value..]\r\n# For example: sqlite:///var/db/radicale.db, postgresql://user:password@localhost/radicale\r\n# See http://docs.sqlalchemy.org/en/rel_0_8/core/engines.html#sqlalchemy.create_engine\r\ndatabase_url = mysql+mysqldb://user:pass@ip:3306/radicale\r\n\r\n\r\n[logging]\r\n# Logging configuration file\r\n# If no config is given, simple information is printed on the standard output\r\n# For more information about the syntax of the configuration file, see:\r\n# http://docs.python.org/library/logging.config.html\r\nconfig = /etc/radicale/logging\r\n# Set the default logging level to debug\r\ndebug = False\r\n# Store all environment variables (including those set in the shell)\r\nfull_environment = False\r\n\r\n\r\n# Additional HTTP headers\r\n#[headers]\r\n#Access-Control-Allow-Origin = *\r\n```"},"comment":{"url":"https://api.github.com/repos/Kozea/Radicale/issues/comments/69936028","html_url":"https://github.com/Kozea/Radicale/issues/253#issuecomment-69936028","issue_url":"https://api.github.com/repos/Kozea/Radicale/issues/253","id":69936028,"user":{"login":"untitaker","id":837573,"avatar_url":"https://avatars.githubusercontent.com/u/837573?v=3","gravatar_id":"","url":"https://api.github.com/users/untitaker","html_url":"https://github.com/untitaker","followers_url":"https://api.github.com/users/untitaker/followers","following_url":"https://api.github.com/users/untitaker/following{/other_user}","gists_url":"https://api.github.com/users/untitaker/gists{/gist_id}","starred_url":"https://api.github.com/users/untitaker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/untitaker/subscriptions","organizations_url":"https://api.github.com/users/untitaker/orgs","repos_url":"https://api.github.com/users/untitaker/repos","events_url":"https://api.github.com/users/untitaker/events{/privacy}","received_events_url":"https://api.github.com/users/untitaker/received_events","type":"User","site_admin":false},"created_at":"2015-01-14T15:46:29Z","updated_at":"2015-01-14T15:46:29Z","body":"@somecallmemike Your log is probably missing stderr. There should be a traceback there because your PUT request points to an invalid filename."}}